diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000..2f786ac8eef05 --- /dev/null +++ b/.clang-format @@ -0,0 +1,71 @@ +# the official .clang-format style for https://github.com/taocpp +# +# clang-format-4.0 -i -style=file $(find -name '[^.]*.[hc]pp') + +Language: Cpp +Standard: Cpp11 + +AccessModifierOffset: -3 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum : true + AfterFunction : true + AfterNamespace : true + AfterStruct : true + AfterUnion : true + BeforeCatch : true + BeforeElse : true + IndentBraces : false +BreakBeforeBinaryOperators: All +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: false +BreakStringLiterals: false +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 0 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 3 +ContinuationIndentWidth: 3 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +IndentWidth: 3 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PointerAlignment: Left +ReflowComments: false +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: true +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: true +SpacesInParentheses: true +SpacesInSquareBrackets: true +TabWidth: 8 +UseTab: Never diff --git a/.clangd b/.clangd new file mode 100644 index 0000000000000..500c5d0d258d6 --- /dev/null +++ b/.clangd @@ -0,0 +1,89 @@ +Diagnostics: + MissingIncludes: None +InlayHints: + Enabled: true + ParameterNames: true + DeducedTypes: true +CompileFlags: + CompilationDatabase: build/ # Search build/ directory for compile_commands.json + Remove: [ -Werror ] + Add: + - -DDEBUG + - -DLOCAL + - -DPGDLLIMPORT= + - -DPIC + - -O2 + - -Wall + - -Wcast-function-type + - -Wconversion + - -Wdeclaration-after-statement + - -Wendif-labels + - -Werror=vla + - -Wextra + - -Wfloat-equal + - -Wformat-security + - -Wimplicit-fallthrough=3 + - -Wmissing-format-attribute + - -Wmissing-prototypes + - -Wno-format-truncation + - -Wno-sign-conversion + - -Wno-stringop-truncation + - -Wno-unused-const-variable + - -Wpointer-arith + - -Wshadow + - -Wshadow=compatible-local + - -fPIC + - -fexcess-precision=standard + - -fno-strict-aliasing + - -fvisibility=hidden + - -fwrapv + - -g + - -std=c11 + - -I. + - -I../../../../src/include +# gcc -E -v -xc++ /dev/null +# - -I/nix/store/l2sgvfcyqc1bgnzpz86qw5pjq99j8vlw-libtool-2.5.4/include +# - -I/nix/store/n087ac9g368fbl6h57a2mdd741lshzrc-file-5.46-dev/include +# - -I/nix/store/p7z72c2s722pbw31jmm3y0nwypksb5fj-gnumake-4.4.1/include +# - -I/nix/store/wzwlizg15dwh6x0h3ckjmibdblfkfdzf-flex-2.6.4/include +# - -I/nix/store/8nh579b2yl3sz2yfwyjc9ksb0jb7kwf5-libxslt-1.1.43-dev/include +# - -I/nix/store/cisb0723v3pgp74f2lj07z5d6w3j77sl-libxml2-2.13.8-dev/include +# - -I/nix/store/245c5yscaxyxi49fz9ys1i1apy5s2igz-valgrind-3.24.0-dev/include +# - -I/nix/store/nmxr110602fvajr9ax8d65ac1g40vx1a-curl-8.13.0-dev/include +# - -I/nix/store/slqvy0fgnwmvaq3bxmrvqclph8x909i2-brotli-1.1.0-dev/include +# - -I/nix/store/lchvccw6zl1z1wmhqayixcjcqyhqvyj7-krb5-1.21.3-dev/include +# - -I/nix/store/hybw3vnacqmm68fskbcchrbmj0h4ffv2-nghttp2-1.65.0-dev/include +# - -I/nix/store/2m0s7qxq2kgclyh6cfbflpxm65aga2h4-libidn2-2.3.8-dev/include +# - -I/nix/store/kcgqglb4iax0zh5jlrxmjdik93wlgsrq-openssl-3.4.1-dev/include +# - -I/nix/store/8mlcjg5js2r0zrpdjlfaxax6hyvppgz5-libpsl-0.21.5-dev/include +# - -I/nix/store/1nygjgimkj4wnmydzd6brsw6m0rd7gmx-libssh2-1.11.1-dev/include +# - -I/nix/store/cbdvjyn19y77m8l06n089x30v7irqz3j-zlib-1.3.1-dev/include +# - -I/nix/store/x10zhllc0rhk1s1mhjvsrzvbg55802gj-zstd-1.5.7-dev/include +# - -I/nix/store/8w718rm43x7z73xhw9d6vh8s4snrq67h-python3-3.12.10/include +# - -I/nix/store/1lrgn56jw2yww4bxj0frpgvahqh9i7gl-perf-linux-6.12.35/include +# - -I/nix/store/j87n5xqfj6c03633g7l95lfjq5ynml13-gdb-16.2/include +# - -I/nix/store/ih8dkkw9r7zx5fxg3arh53qc9zs422d1-llvm-21.1.0-dev/include +# - -I/nix/store/rz4bmcm8dwsy7ylx6rhffkwkqn6n8srn-ncurses-6.5-dev/include +# - -I/nix/store/29mcvdnd9s6sp46cjmqm0pfg4xs56rik-zlib-1.3.1-dev/include +# - -I/nix/store/42288hw25sc2gchgc5jp4wfgwisa0nxm-lldb-21.1.0-dev/include +# - -I/nix/store/wpfdp7vzd7h7ahnmp4rvxfcklg4viknl-tcl-8.6.15/include +# - -I/nix/store/4sq2x2770k0xrjshdi6piqrazqjfi5s4-readline-8.2p13-dev/include +# - -I/nix/store/myw381bc9yqd709hpray9lp7l98qmlm1-ncurses-6.5-dev/include +# - -I/nix/store/dvhx24q4icrig4q1v1lp7kzi3izd5jmb-icu4c-76.1-dev/include +# - -I/nix/store/7ld4hdn561a4vkk5hrkdhq8r6rxw8shl-lz4-1.10.0-dev/include +# - -I/nix/store/fnzbi6b8q79faggzj53paqi7igr091w0-util-linux-minimal-2.41-dev/include +# - -I/nix/store/vrdwlbzr74ibnzcli2yl1nxg9jqmr237-linux-pam-1.6.1/include +# - -I/nix/store/qizipyz9y17nr4w4gmxvwd3x4k0bp2rh-libxcrypt-4.4.38/include +# - -I/nix/store/7z8illxfqr4mvwh4l3inik6vdh12jx09-numactl-2.0.18-dev/include +# - -I/nix/store/f6lmz5inbk7qjc79099q4jvgzih7zbhy-openldap-2.6.9-dev/include +# - -I/nix/store/28vmjd90wzd6gij5a1nfj4nqaw191cfg-liburing-2.9-dev/include +# - -I/nix/store/75cyhmjxzx8z7v2z8vrmrydwraf00wyi-libselinux-3.8.1-dev/include +# - -I/nix/store/r25srliigrrv5q3n7y8ms6z10spvjcd9-glibc-2.40-66-dev/include +# - -I/nix/store/ldp1izmflvc74bd4n2svhrd5xrz61wyi-lld-21.1.0-dev/include +# - -I/nix/store/wd5cm50kmlw8n9mq6l1mkvpp8g443a1g-compiler-rt-libc-21.1.0-dev/include +# - -I/nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322/ +# - -I/nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322//x86_64-unknown-linux-gnu +# - -I/nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include/c++/14.2.1.20250322//backward +# - -I/nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/lib/gcc/x86_64-unknown-linux-gnu/14.2.1/include +# - -I/nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/include +# - -I/nix/store/9ds850ifd4jwcccpp3v14818kk74ldf2-gcc-14.2.1.20250322/lib/gcc/x86_64-unknown-linux-gnu/14.2.1/include-fixed diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000000..c2f6763607e61 --- /dev/null +++ b/.envrc @@ -0,0 +1,9 @@ +watch_file flake.nix +use flake + +#export MESON_EXTRA_SETUP="-Db_coverage=true" +#export GENINFO_OPTIONS="--ignore-errors inconsistent,gcov" +#export LCOV_OPTIONS="--ignore-errors inconsistent,gcov" + +export CFLAGS="-Wall -Wextra -Wconversion -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion -fsanitize-trap --werror" +# -fsanitize=undefined,address,undefined,thread diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000000000..0a548eb87cdf7 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,2 @@ +set tui tab-width 4 +set tui mouse-events off diff --git a/.gitignore b/.gitignore index 4e911395fe3ba..8e429d66ca41f 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,11 @@ lib*.pc /Release/ /tmp_install/ /portlock/ + +build/ +install/ +test-db/ +.direnv/ +.cache/ +.history + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000..13566b81b018a --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/editor.xml b/.idea/editor.xml new file mode 100644 index 0000000000000..1f0ef49b4faf4 --- /dev/null +++ b/.idea/editor.xml @@ -0,0 +1,580 @@ + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000000..9c69411050eac --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000..53624c9e1f9ab --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 0000000000000..b0c1c68fbbad6 --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000..35eb1ddfbbc02 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000000..f5d97424c5047 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Attach Postgres", + "type": "cppdbg", + "request": "attach", + "program": "${workspaceRoot}/install/bin/postgres", + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000..cc8a64fa9fa85 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "syscache.h": "c" + } +} \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000000..a609589066525 --- /dev/null +++ b/flake.lock @@ -0,0 +1,78 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1751211869, + "narHash": "sha256-1Cu92i1KSPbhPCKxoiVG5qnoRiKTgR5CcGSRyLpOd7Y=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b43c397f6c213918d6cfe6e3550abfe79b5d1c51", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1757651841, + "narHash": "sha256-Lh9QoMzTjY/O4LqNwcm6s/WSYStDmCH6f3V/izwlkHc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ad4e6dd68c30bc8bd1860a27bc6f0c485bd7f3b6", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000000..709d13737ee5a --- /dev/null +++ b/flake.nix @@ -0,0 +1,45 @@ +{ + description = "PostgreSQL development environment"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { + self, + nixpkgs, + nixpkgs-unstable, + flake-utils, + }: + flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = import nixpkgs { + inherit system; + config.allowUnfree = true; + }; + pkgs-unstable = import nixpkgs-unstable { + inherit system; + config.allowUnfree = true; + }; + + shellConfig = import ./shell.nix {inherit pkgs pkgs-unstable system;}; + in { + formatter = pkgs.alejandra; + devShells = { + default = shellConfig.devShell; + gcc = shellConfig.devShell; + clang = shellConfig.clangDevShell; + gcc-musl = shellConfig.muslDevShell; + clang-musl = shellConfig.clangMuslDevShell; + }; + + packages = { + inherit (shellConfig) gdbConfig flameGraphScript pgbenchScript; + }; + + environment.localBinInPath = true; + } + ); +} diff --git a/glibc-no-fortify-warning.patch b/glibc-no-fortify-warning.patch new file mode 100644 index 0000000000000..681e678e67ee3 --- /dev/null +++ b/glibc-no-fortify-warning.patch @@ -0,0 +1,24 @@ +From 130c231020f97e5eb878cc9fdb2bd9b186a5aa04 Mon Sep 17 00:00:00 2001 +From: Greg Burd +Date: Fri, 24 Oct 2025 11:58:24 -0400 +Subject: [PATCH] no warnings with -O0 and fortify source please + +--- + include/features.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/features.h b/include/features.h +index 673c4036..a02c8a3f 100644 +--- a/include/features.h ++++ b/include/features.h +@@ -432,7 +432,6 @@ + + #if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0 + # if !defined __OPTIMIZE__ || __OPTIMIZE__ <= 0 +-# warning _FORTIFY_SOURCE requires compiling with optimization (-O) + # elif !__GNUC_PREREQ (4, 1) + # warning _FORTIFY_SOURCE requires GCC 4.1 or later + # elif _FORTIFY_SOURCE > 2 && (__glibc_clang_prereq (9, 0) \ +-- +2.50.1 + diff --git a/pg-aliases.sh b/pg-aliases.sh new file mode 100644 index 0000000000000..80c5a67853c15 --- /dev/null +++ b/pg-aliases.sh @@ -0,0 +1,304 @@ +# PostgreSQL Development Aliases + +# Build system management +pg_clean_for_compiler() { + local current_compiler="$(basename $CC)" + local build_dir="$PG_BUILD_DIR" + + if [ -f "$build_dir/compile_commands.json" ]; then + local last_compiler=$(grep -o '/[^/]*/bin/[gc]cc\|/[^/]*/bin/clang' "$build_dir/compile_commands.json" | head -1 | xargs basename 2>/dev/null || echo "unknown") + + if [ "$last_compiler" != "$current_compiler" ] && [ "$last_compiler" != "unknown" ]; then + echo "Detected compiler change from $last_compiler to $current_compiler" + echo "Cleaning build directory..." + rm -rf "$build_dir" + mkdir -p "$build_dir" + fi + fi + + mkdir -p "$build_dir" + echo "$current_compiler" >"$build_dir/.compiler_used" +} + +# Core PostgreSQL commands +alias pg-setup=' + if [ -z "$PERL_CORE_DIR" ]; then + echo "Error: Could not find perl CORE directory" >&2 + return 1 + fi + + pg_clean_for_compiler + + echo "=== PostgreSQL Build Configuration ===" + echo "Compiler: $CC" + echo "LLVM: $(llvm-config --version 2>/dev/null || echo 'disabled')" + echo "Source: $PG_SOURCE_DIR" + echo "Build: $PG_BUILD_DIR" + echo "Install: $PG_INSTALL_DIR" + echo "======================================" + # --fatal-meson-warnings + + env CFLAGS="-I$PERL_CORE_DIR $CFLAGS" \ + LDFLAGS="-L$PERL_CORE_DIR -lperl $LDFLAGS" \ + meson setup $MESON_EXTRA_SETUP \ + --reconfigure \ + -Db_coverage=false \ + -Db_lundef=false \ + -Dcassert=true \ + -Ddebug=true \ + -Ddocs_html_style=website \ + -Ddocs_pdf=enabled \ + -Dicu=enabled \ + -Dinjection_points=true \ + -Dldap=enabled \ + -Dlibcurl=enabled \ + -Dlibxml=enabled \ + -Dlibxslt=enabled \ + -Dllvm=auto \ + -Dlz4=enabled \ + -Dnls=enabled \ + -Doptimization=g \ + -Dplperl=enabled \ + -Dplpython=enabled \ + -Dpltcl=enabled \ + -Dreadline=enabled \ + -Dssl=openssl \ + -Dtap_tests=enabled \ + -Duuid=e2fs \ + -Dzstd=enabled \ + --prefix="$PG_INSTALL_DIR" \ + "$PG_BUILD_DIR" \ + "$PG_SOURCE_DIR"' + +alias pg-compdb='compdb -p build/ list > compile_commands.json' +alias pg-build='meson compile -C "$PG_BUILD_DIR"' +alias pg-install='meson install -C "$PG_BUILD_DIR"' +alias pg-test='meson test -q --print-errorlogs -C "$PG_BUILD_DIR"' + +# Clean commands +alias pg-clean='ninja -C "$PG_BUILD_DIR" clean' +alias pg-full-clean='rm -rf "$PG_BUILD_DIR" "$PG_INSTALL_DIR" && echo "Build and install directories cleaned"' + +# Database management +alias pg-init='rm -rf "$PG_DATA_DIR" && "$PG_INSTALL_DIR/bin/initdb" --debug --no-clean "$PG_DATA_DIR"' +alias pg-start='"$PG_INSTALL_DIR/bin/postgres" -D "$PG_DATA_DIR" -k "$PG_DATA_DIR"' +alias pg-stop='pkill -f "postgres.*-D.*$PG_DATA_DIR" || true' +alias pg-restart='pg-stop && sleep 2 && pg-start' +alias pg-status='pgrep -f "postgres.*-D.*$PG_DATA_DIR" && echo "PostgreSQL is running" || echo "PostgreSQL is not running"' + +# Client connections +alias pg-psql='"$PG_INSTALL_DIR/bin/psql" -h "$PG_DATA_DIR" postgres' +alias pg-createdb='"$PG_INSTALL_DIR/bin/createdb" -h "$PG_DATA_DIR"' +alias pg-dropdb='"$PG_INSTALL_DIR/bin/dropdb" -h "$PG_DATA_DIR"' + +# Debugging +alias pg-debug-gdb='gdb -x "$GDBINIT" "$PG_INSTALL_DIR/bin/postgres"' +alias pg-debug-lldb='lldb "$PG_INSTALL_DIR/bin/postgres"' +alias pg-debug=' + if command -v gdb >/dev/null 2>&1; then + pg-debug-gdb + elif command -v lldb >/dev/null 2>&1; then + pg-debug-lldb + else + echo "No debugger available (gdb or lldb required)" + fi' + +# Attach to running process +alias pg-attach-gdb=' + PG_PID=$(pgrep -f "postgres.*-D.*$PG_DATA_DIR" | head -1) + if [ -n "$PG_PID" ]; then + echo "Attaching GDB to PostgreSQL process $PG_PID" + gdb -x "$GDBINIT" -p "$PG_PID" + else + echo "No PostgreSQL process found" + fi' + +alias pg-attach-lldb=' + PG_PID=$(pgrep -f "postgres.*-D.*$PG_DATA_DIR" | head -1) + if [ -n "$PG_PID" ]; then + echo "Attaching LLDB to PostgreSQL process $PG_PID" + lldb -p "$PG_PID" + else + echo "No PostgreSQL process found" + fi' + +alias pg-attach=' + if command -v gdb >/dev/null 2>&1; then + pg-attach-gdb + elif command -v lldb >/dev/null 2>&1; then + pg-attach-lldb + else + echo "No debugger available (gdb or lldb required)" + fi' + +# Performance profiling and analysis +alias pg-valgrind='valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all "$PG_INSTALL_DIR/bin/postgres" -D "$PG_DATA_DIR"' +alias pg-strace='strace -f -o /tmp/postgres.strace "$PG_INSTALL_DIR/bin/postgres" -D "$PG_DATA_DIR"' + +# Flame graph generation +alias pg-flame='pg-flame-generate' +alias pg-flame-30='pg-flame-generate 30' +alias pg-flame-60='pg-flame-generate 60' +alias pg-flame-120='pg-flame-generate 120' + +# Custom flame graph with specific duration and output +pg-flame-custom() { + local duration=${1:-30} + local output_dir=${2:-$PG_FLAME_DIR} + echo "Generating flame graph for ${duration}s, output to: $output_dir" + pg-flame-generate "$duration" "$output_dir" +} + +# Benchmarking with pgbench +alias pg-bench='pg-bench-run' +alias pg-bench-quick='pg-bench-run 5 1 100 1 30 select-only' +alias pg-bench-standard='pg-bench-run 10 2 1000 10 60 tpcb-like' +alias pg-bench-heavy='pg-bench-run 50 4 5000 100 300 tpcb-like' +alias pg-bench-readonly='pg-bench-run 20 4 2000 50 120 select-only' + +# Custom benchmark function +pg-bench-custom() { + local clients=${1:-10} + local threads=${2:-2} + local transactions=${3:-1000} + local scale=${4:-10} + local duration=${5:-60} + local test_type=${6:-tpcb-like} + + echo "Running custom benchmark:" + echo " Clients: $clients, Threads: $threads" + echo " Transactions: $transactions, Scale: $scale" + echo " Duration: ${duration}s, Type: $test_type" + + pg-bench-run "$clients" "$threads" "$transactions" "$scale" "$duration" "$test_type" +} + +# Benchmark with flame graph +pg-bench-flame() { + local duration=${1:-60} + local clients=${2:-10} + local scale=${3:-10} + + echo "Running benchmark with flame graph generation" + echo "Duration: ${duration}s, Clients: $clients, Scale: $scale" + + # Start benchmark in background + pg-bench-run "$clients" 2 1000 "$scale" "$duration" tpcb-like & + local bench_pid=$! + + # Wait a bit for benchmark to start + sleep 5 + + # Generate flame graph for most of the benchmark duration + local flame_duration=$((duration - 10)) + if [ $flame_duration -gt 10 ]; then + pg-flame-generate "$flame_duration" & + local flame_pid=$! + fi + + # Wait for benchmark to complete + wait $bench_pid + + # Wait for flame graph if it was started + if [ -n "${flame_pid:-}" ]; then + wait $flame_pid + fi + + echo "Benchmark and flame graph generation completed" +} + +# Performance monitoring +alias pg-perf='perf top -p $(pgrep -f "postgres.*-D.*$PG_DATA_DIR" | head -1)' +alias pg-htop='htop -p $(pgrep -f "postgres.*-D.*$PG_DATA_DIR" | tr "\n" "," | sed "s/,$//")' + +# System performance stats during PostgreSQL operation +pg-stats() { + local duration=${1:-30} + echo "Collecting system stats for ${duration}s..." + + iostat -x 1 "$duration" >"$PG_BENCH_DIR/iostat_$(date +%Y%m%d_%H%M%S).log" & + vmstat 1 "$duration" >"$PG_BENCH_DIR/vmstat_$(date +%Y%m%d_%H%M%S).log" & + + wait + echo "System stats saved to $PG_BENCH_DIR" +} + +# Development helpers +pg-format() { + local since=${1:-HEAD} + + if [ ! -f "$PG_SOURCE_DIR/src/tools/pgindent/pgindent" ]; then + echo "Error: pgindent not found at $PG_SOURCE_DIR/src/tools/pgindent/pgindent" + else + + modified_files=$(git diff --name-only "${since}" | grep -E "\.c$|\.h$") + + if [ -z "$modified_files" ]; then + echo "No modified .c or .h files found" + else + + echo "Formatting modified files with pgindent:" + for file in $modified_files; do + if [ -f "$file" ]; then + echo " Formatting: $file" + "$PG_SOURCE_DIR/src/tools/pgindent/pgindent" "$file" + else + echo " Warning: File not found: $file" + fi + done + + echo "Checking files for whitespace:" + git diff --check "${since}" + fi + fi +} + +alias pg-tidy='find "$PG_SOURCE_DIR" -name "*.c" | head -10 | xargs clang-tidy' + +# Log management +alias pg-log='tail -f "$PG_DATA_DIR/log/postgresql-$(date +%Y-%m-%d).log" 2>/dev/null || echo "No log file found"' +alias pg-log-errors='grep -i error "$PG_DATA_DIR/log/"*.log 2>/dev/null || echo "No error logs found"' + +# Build logs +alias pg-build-log='cat "$PG_BUILD_DIR/meson-logs/meson-log.txt"' +alias pg-build-errors='grep -i error "$PG_BUILD_DIR/meson-logs/meson-log.txt" 2>/dev/null || echo "No build errors found"' + +# Results viewing +alias pg-bench-results='ls -la "$PG_BENCH_DIR" && echo "Latest results:" && tail -20 "$PG_BENCH_DIR"/results_*.txt 2>/dev/null | tail -20' +alias pg-flame-results='ls -la "$PG_FLAME_DIR" && echo "Open flame graphs with: firefox $PG_FLAME_DIR/*.svg"' + +# Clean up old results +pg-clean-results() { + local days=${1:-7} + echo "Cleaning benchmark and flame graph results older than $days days..." + find "$PG_BENCH_DIR" -type f -mtime +$days -delete 2>/dev/null || true + find "$PG_FLAME_DIR" -type f -mtime +$days -delete 2>/dev/null || true + echo "Cleanup completed" +} + +# Information +alias pg-info=' + echo "=== PostgreSQL Development Environment ===" + echo "Source: $PG_SOURCE_DIR" + echo "Build: $PG_BUILD_DIR" + echo "Install: $PG_INSTALL_DIR" + echo "Data: $PG_DATA_DIR" + echo "Benchmarks: $PG_BENCH_DIR" + echo "Flame graphs: $PG_FLAME_DIR" + echo "Compiler: $CC" + echo "" + echo "Available commands:" + echo " Setup: pg-setup, pg-build, pg-install" + echo " Database: pg-init, pg-start, pg-stop, pg-psql" + echo " Debug: pg-debug, pg-attach, pg-valgrind" + echo " Performance: pg-flame, pg-bench, pg-perf" + echo " Benchmarks: pg-bench-quick, pg-bench-standard, pg-bench-heavy" + echo " Flame graphs: pg-flame-30, pg-flame-60, pg-flame-custom" + echo " Combined: pg-bench-flame" + echo " Results: pg-bench-results, pg-flame-results" + echo " Logs: pg-log, pg-build-log" + echo " Clean: pg-clean, pg-full-clean, pg-clean-results" + echo " Code quality: pg-format, pg-tidy" + echo "=========================================="' + +echo "PostgreSQL aliases loaded. Run 'pg-info' for available commands." diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000000000..130d5b21986b2 --- /dev/null +++ b/shell.nix @@ -0,0 +1,820 @@ +{ + pkgs, + pkgs-unstable, + system, +}: let + # Create a patched glibc only for the dev shell + patchedGlibc = pkgs.glibc.overrideAttrs (oldAttrs: { + patches = (oldAttrs.patches or []) ++ [ + ./glibc-no-fortify-warning.patch + ]; + }); + + llvmPkgs = pkgs-unstable.llvmPackages_21; + + # Configuration constants + config = { + pgSourceDir = "$PWD"; + pgBuildDir = "$PWD/build"; + pgInstallDir = "$PWD/install"; + pgDataDir = "/tmp/test-db-$(basename $PWD)"; + pgBenchDir = "/tmp/pgbench-results-$(basename $PWD)"; + pgFlameDir = "/tmp/flame-graphs-$(basename $PWD)"; + }; + + # Single dependency function that can be used for all environments + getPostgreSQLDeps = muslLibs: + with pkgs; + [ + # Build system (always use host tools) + pkgs-unstable.meson + pkgs-unstable.ninja + pkg-config + autoconf + libtool + git + which + binutils + gnumake + + # Parser/lexer tools + bison + flex + + # Documentation + docbook_xml_dtd_45 + docbook-xsl-nons + fop + gettext + libxslt + libxml2 + + # Development tools (always use host tools) + coreutils + shellcheck + ripgrep + valgrind + curl + uv + pylint + black + lcov + strace + ltrace + perf-tools + linuxPackages.perf + flamegraph + htop + iotop + sysstat + ccache + cppcheck + compdb + + # GCC/GDB +# pkgs-unstable.gcc15 + gcc + gdb + + # LLVM toolchain + llvmPkgs.llvm + llvmPkgs.llvm.dev + llvmPkgs.clang-tools + llvmPkgs.lldb + + # Language support + (perl.withPackages (ps: with ps; [IPCRun])) + (python3.withPackages (ps: with ps; [requests browser-cookie3])) + tcl + ] + ++ ( + if muslLibs + then [ + # Musl target libraries for cross-compilation + pkgs.pkgsMusl.readline + pkgs.pkgsMusl.zlib + pkgs.pkgsMusl.openssl + pkgs.pkgsMusl.icu + pkgs.pkgsMusl.lz4 + pkgs.pkgsMusl.zstd + pkgs.pkgsMusl.libuuid + pkgs.pkgsMusl.libkrb5 + pkgs.pkgsMusl.linux-pam + pkgs.pkgsMusl.libxcrypt + ] + else [ + # Glibc target libraries + readline + zlib + openssl + icu + lz4 + zstd + libuuid + libkrb5 + linux-pam + libxcrypt + numactl + openldap + liburing + libselinux + patchedGlibc + glibcInfo + glibc.dev + ] + ); + + # GDB configuration for PostgreSQL debugging + gdbConfig = pkgs.writeText "gdbinit-postgres" '' + # PostgreSQL-specific GDB configuration + + # Pretty-print PostgreSQL data structures + define print_node + if $arg0 + printf "Node type: %s\n", nodeTagNames[$arg0->type] + print *$arg0 + else + printf "NULL node\n" + end + end + document print_node + Print a PostgreSQL Node with type information + Usage: print_node + end + + define print_list + set $list = (List*)$arg0 + if $list + printf "List length: %d\n", $list->length + set $cell = $list->head + set $i = 0 + while $cell && $i < $list->length + printf " [%d]: ", $i + print_node $cell->data.ptr_value + set $cell = $cell->next + set $i = $i + 1 + end + else + printf "NULL list\n" + end + end + document print_list + Print a PostgreSQL List structure + Usage: print_list + end + + define print_query + set $query = (Query*)$arg0 + if $query + printf "Query type: %d, command type: %d\n", $query->querySource, $query->commandType + print *$query + else + printf "NULL query\n" + end + end + document print_query + Print a PostgreSQL Query structure + Usage: print_query + end + + define print_relcache + set $rel = (Relation)$arg0 + if $rel + printf "Relation: %s.%s (OID: %u)\n", $rel->rd_rel->relnamespace, $rel->rd_rel->relname.data, $rel->rd_id + printf " natts: %d, relkind: %c\n", $rel->rd_rel->relnatts, $rel->rd_rel->relkind + else + printf "NULL relation\n" + end + end + document print_relcache + Print relation cache entry information + Usage: print_relcache + end + + define print_tupdesc + set $desc = (TupleDesc)$arg0 + if $desc + printf "TupleDesc: %d attributes\n", $desc->natts + set $i = 0 + while $i < $desc->natts + set $attr = $desc->attrs[$i] + printf " [%d]: %s (type: %u, len: %d)\n", $i, $attr->attname.data, $attr->atttypid, $attr->attlen + set $i = $i + 1 + end + else + printf "NULL tuple descriptor\n" + end + end + document print_tupdesc + Print tuple descriptor information + Usage: print_tupdesc + end + + define print_slot + set $slot = (TupleTableSlot*)$arg0 + if $slot + printf "TupleTableSlot: %s\n", $slot->tts_ops->name + printf " empty: %d, shouldFree: %d\n", $slot->tts_empty, $slot->tts_shouldFree + if $slot->tts_tupleDescriptor + print_tupdesc $slot->tts_tupleDescriptor + end + else + printf "NULL slot\n" + end + end + document print_slot + Print tuple table slot information + Usage: print_slot + end + + # Memory context debugging + define print_mcxt + set $context = (MemoryContext)$arg0 + if $context + printf "MemoryContext: %s\n", $context->name + printf " type: %s, parent: %p\n", $context->methods->name, $context->parent + printf " total: %zu, free: %zu\n", $context->mem_allocated, $context->freep - $context->freeptr + else + printf "NULL memory context\n" + end + end + document print_mcxt + Print memory context information + Usage: print_mcxt + end + + # Process debugging + define print_proc + set $proc = (PGPROC*)$arg0 + if $proc + printf "PGPROC: pid=%d, database=%u\n", $proc->pid, $proc->databaseId + printf " waiting: %d, waitStatus: %d\n", $proc->waiting, $proc->waitStatus + else + printf "NULL process\n" + end + end + document print_proc + Print process information + Usage: print_proc + end + + # Set useful defaults + set print pretty on + set print object on + set print static-members off + set print vtbl on + set print demangle on + set demangle-style gnu-v3 + set print sevenbit-strings off + set history save on + set history size 1000 + set history filename ~/.gdb_history_postgres + + # Common breakpoints for PostgreSQL debugging + define pg_break_common + break elog + break errfinish + break ExceptionalCondition + break ProcessInterrupts + end + document pg_break_common + Set common PostgreSQL debugging breakpoints + end + + printf "PostgreSQL GDB configuration loaded.\n" + printf "Available commands: print_node, print_list, print_query, print_relcache,\n" + printf " print_tupdesc, print_slot, print_mcxt, print_proc, pg_break_common\n" + ''; + + # Flame graph generation script + flameGraphScript = pkgs.writeScriptBin "pg-flame-generate" '' + #!${pkgs.bash}/bin/bash + set -euo pipefail + + DURATION=''${1:-30} + OUTPUT_DIR=''${2:-${config.pgFlameDir}} + TIMESTAMP=$(date +%Y%m%d_%H%M%S) + + mkdir -p "$OUTPUT_DIR" + + echo "Generating flame graph for PostgreSQL (duration: ''${DURATION}s)" + + # Find PostgreSQL processes + PG_PIDS=$(pgrep -f "postgres.*-D.*${config.pgDataDir}" || true) + + if [ -z "$PG_PIDS" ]; then + echo "Error: No PostgreSQL processes found" + exit 1 + fi + + echo "Found PostgreSQL processes: $PG_PIDS" + + # Record perf data + PERF_DATA="$OUTPUT_DIR/perf_$TIMESTAMP.data" + echo "Recording perf data to $PERF_DATA" + + ${pkgs.linuxPackages.perf}/bin/perf record \ + -F 997 \ + -g \ + --call-graph dwarf \ + -p "$(echo $PG_PIDS | tr ' ' ',')" \ + -o "$PERF_DATA" \ + sleep "$DURATION" + + # Generate flame graph + FLAME_SVG="$OUTPUT_DIR/postgres_flame_$TIMESTAMP.svg" + echo "Generating flame graph: $FLAME_SVG" + + ${pkgs.linuxPackages.perf}/bin/perf script -i "$PERF_DATA" | \ + ${pkgs.flamegraph}/bin/stackcollapse-perf.pl | \ + ${pkgs.flamegraph}/bin/flamegraph.pl \ + --title "PostgreSQL Flame Graph ($TIMESTAMP)" \ + --width 1200 \ + --height 800 \ + > "$FLAME_SVG" + + echo "Flame graph generated: $FLAME_SVG" + echo "Perf data saved: $PERF_DATA" + + # Generate summary report + REPORT="$OUTPUT_DIR/report_$TIMESTAMP.txt" + echo "Generating performance report: $REPORT" + + { + echo "PostgreSQL Performance Analysis Report" + echo "Generated: $(date)" + echo "Duration: ''${DURATION}s" + echo "Processes: $PG_PIDS" + echo "" + echo "=== Top Functions ===" + ${pkgs.linuxPackages.perf}/bin/perf report -i "$PERF_DATA" --stdio --sort comm,dso,symbol | head -50 + echo "" + echo "=== Call Graph ===" + ${pkgs.linuxPackages.perf}/bin/perf report -i "$PERF_DATA" --stdio -g --sort comm,dso,symbol | head -100 + } > "$REPORT" + + echo "Report generated: $REPORT" + echo "" + echo "Files created:" + echo " Flame graph: $FLAME_SVG" + echo " Perf data: $PERF_DATA" + echo " Report: $REPORT" + ''; + + # pgbench wrapper script + pgbenchScript = pkgs.writeScriptBin "pg-bench-run" '' + #!${pkgs.bash}/bin/bash + set -euo pipefail + + # Default parameters + CLIENTS=''${1:-10} + THREADS=''${2:-2} + TRANSACTIONS=''${3:-1000} + SCALE=''${4:-10} + DURATION=''${5:-60} + TEST_TYPE=''${6:-tpcb-like} + + OUTPUT_DIR="${config.pgBenchDir}" + TIMESTAMP=$(date +%Y%m%d_%H%M%S) + + mkdir -p "$OUTPUT_DIR" + + echo "=== PostgreSQL Benchmark Configuration ===" + echo "Clients: $CLIENTS" + echo "Threads: $THREADS" + echo "Transactions: $TRANSACTIONS" + echo "Scale factor: $SCALE" + echo "Duration: ''${DURATION}s" + echo "Test type: $TEST_TYPE" + echo "Output directory: $OUTPUT_DIR" + echo "============================================" + + # Check if PostgreSQL is running + if ! pgrep -f "postgres.*-D.*${config.pgDataDir}" >/dev/null; then + echo "Error: PostgreSQL is not running. Start it with 'pg-start'" + exit 1 + fi + + PGBENCH="${config.pgInstallDir}/bin/pgbench" + PSQL="${config.pgInstallDir}/bin/psql" + CREATEDB="${config.pgInstallDir}/bin/createdb" + DROPDB="${config.pgInstallDir}/bin/dropdb" + + DB_NAME="pgbench_test_$TIMESTAMP" + RESULTS_FILE="$OUTPUT_DIR/results_$TIMESTAMP.txt" + LOG_FILE="$OUTPUT_DIR/pgbench_$TIMESTAMP.log" + + echo "Creating test database: $DB_NAME" + "$CREATEDB" -h "${config.pgDataDir}" "$DB_NAME" || { + echo "Failed to create database" + exit 1 + } + + # Initialize pgbench tables + echo "Initializing pgbench tables (scale factor: $SCALE)" + "$PGBENCH" -h "${config.pgDataDir}" -i -s "$SCALE" "$DB_NAME" || { + echo "Failed to initialize pgbench tables" + "$DROPDB" -h "${config.pgDataDir}" "$DB_NAME" 2>/dev/null || true + exit 1 + } + + # Run benchmark based on test type + echo "Running benchmark..." + + case "$TEST_TYPE" in + "tpcb-like"|"default") + BENCH_ARGS="" + ;; + "select-only") + BENCH_ARGS="-S" + ;; + "simple-update") + BENCH_ARGS="-N" + ;; + "read-write") + BENCH_ARGS="-b select-only@70 -b tpcb-like@30" + ;; + *) + echo "Unknown test type: $TEST_TYPE" + echo "Available types: tpcb-like, select-only, simple-update, read-write" + "$DROPDB" -h "${config.pgDataDir}" "$DB_NAME" 2>/dev/null || true + exit 1 + ;; + esac + + { + echo "PostgreSQL Benchmark Results" + echo "Generated: $(date)" + echo "Test type: $TEST_TYPE" + echo "Clients: $CLIENTS, Threads: $THREADS" + echo "Transactions: $TRANSACTIONS, Duration: ''${DURATION}s" + echo "Scale factor: $SCALE" + echo "Database: $DB_NAME" + echo "" + echo "=== System Information ===" + echo "CPU: $(nproc) cores" + echo "Memory: $(free -h | grep '^Mem:' | awk '{print $2}')" + echo "Compiler: $CC" + echo "PostgreSQL version: $("$PSQL" --no-psqlrc -h "${config.pgDataDir}" -d "$DB_NAME" -t -c "SELECT version();" | head -1)" + echo "" + echo "=== Benchmark Results ===" + } > "$RESULTS_FILE" + + # Run the actual benchmark + "$PGBENCH" \ + -h "${config.pgDataDir}" \ + -c "$CLIENTS" \ + -j "$THREADS" \ + -T "$DURATION" \ + -P 5 \ + --log \ + --log-prefix="$OUTPUT_DIR/pgbench_$TIMESTAMP" \ + $BENCH_ARGS \ + "$DB_NAME" 2>&1 | tee -a "$RESULTS_FILE" + + # Collect additional statistics + { + echo "" + echo "=== Database Statistics ===" + "$PSQL" --no-psqlrc -h "${config.pgDataDir}" -d "$DB_NAME" -c " + SELECT + schemaname, + relname, + n_tup_ins as inserts, + n_tup_upd as updates, + n_tup_del as deletes, + n_live_tup as live_tuples, + n_dead_tup as dead_tuples + FROM pg_stat_user_tables; + " + + echo "" + echo "=== Index Statistics ===" + "$PSQL" --no-psqlrc -h "${config.pgDataDir}" -d "$DB_NAME" -c " + SELECT + schemaname, + relname, + indexrelname, + idx_scan, + idx_tup_read, + idx_tup_fetch + FROM pg_stat_user_indexes; + " + } >> "$RESULTS_FILE" + + # Clean up + echo "Cleaning up test database: $DB_NAME" + "$DROPDB" -h "${config.pgDataDir}" "$DB_NAME" 2>/dev/null || true + + echo "" + echo "Benchmark completed!" + echo "Results saved to: $RESULTS_FILE" + echo "Transaction logs: $OUTPUT_DIR/pgbench_$TIMESTAMP*" + + # Show summary + echo "" + echo "=== Quick Summary ===" + grep -E "(tps|latency)" "$RESULTS_FILE" | tail -5 + ''; + + # Development shell (GCC + glibc) + devShell = pkgs.mkShell { + name = "postgresql-dev"; + buildInputs = + (getPostgreSQLDeps false) + ++ [ + flameGraphScript + pgbenchScript + ]; + + shellHook = let + icon = "f121"; + in '' + # History configuration + export HISTFILE=.history + export HISTSIZE=1000000 + export HISTFILESIZE=1000000 + + # Clean environment + unset LD_LIBRARY_PATH LD_PRELOAD LIBRARY_PATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH + + # Essential tools in PATH + export PATH="${pkgs.which}/bin:${pkgs.coreutils}/bin:$PATH" + export PS1="$(echo -e '\u${icon}') {\[$(tput sgr0)\]\[\033[38;5;228m\]\w\[$(tput sgr0)\]\[\033[38;5;15m\]} ($(git rev-parse --abbrev-ref HEAD)) \\$ \[$(tput sgr0)\]" + + # Ccache configuration + export PATH=${pkgs.ccache}/bin:$PATH + export CCACHE_COMPILERCHECK=content + export CCACHE_DIR=$HOME/.ccache/pg/$(basename $PWD) + mkdir -p "$CCACHE_DIR" + + # LLVM configuration + export LLVM_CONFIG="${llvmPkgs.llvm}/bin/llvm-config" + export PATH="${llvmPkgs.llvm}/bin:$PATH" + export PKG_CONFIG_PATH="${llvmPkgs.llvm.dev}/lib/pkgconfig:$PKG_CONFIG_PATH" + export LLVM_DIR="${llvmPkgs.llvm.dev}/lib/cmake/llvm" + export LLVM_ROOT="${llvmPkgs.llvm}" + + # Development tools in PATH + export PATH=${pkgs.clang-tools}/bin:$PATH + export PATH=${pkgs.cppcheck}/bin:$PATH + + # PosgreSQL Development CFLAGS + # -DRELCACHE_FORCE_RELEASE -DCATCACHE_FORCE_RELEASE -fno-omit-frame-pointer -fno-stack-protector -DUSE_VALGRIND + export CFLAGS="" + export CXXFLAGS="" + + # Python UV + UV_PYTHON_DOWNLOADS=never + + # GCC configuration (default compiler) + export CC="${pkgs.gcc}/bin/gcc" + export CXX="${pkgs.gcc}/bin/g++" + + # PostgreSQL environment + export PG_SOURCE_DIR="${config.pgSourceDir}" + export PG_BUILD_DIR="${config.pgBuildDir}" + export PG_INSTALL_DIR="${config.pgInstallDir}" + export PG_DATA_DIR="${config.pgDataDir}" + export PG_BENCH_DIR="${config.pgBenchDir}" + export PG_FLAME_DIR="${config.pgFlameDir}" + export PERL_CORE_DIR=$(find ${pkgs.perl} -maxdepth 5 -path "*/CORE" -type d) + + # GDB configuration + export GDBINIT="${gdbConfig}" + + # Performance tools in PATH + export PATH="${flameGraphScript}/bin:${pgbenchScript}/bin:$PATH" + + # Create output directories + mkdir -p "$PG_BENCH_DIR" "$PG_FLAME_DIR" + + # Compiler verification + echo "Environment configured:" + echo " Compiler: $CC" + echo " libc: glibc" + echo " LLVM: $(llvm-config --version 2>/dev/null || echo 'not available')" + + # Load PostgreSQL development aliases + if [ -f ./pg-aliases.sh ]; then + source ./pg-aliases.sh + else + echo "Warning: pg-aliases.sh not found in current directory" + fi + + echo "" + echo "PostgreSQL Development Environment Ready (GCC + glibc)" + echo "Run 'pg-info' for available commands" + ''; + }; + + # Clang + glibc variant + clangDevShell = pkgs.mkShell { + name = "postgresql-clang-glibc"; + buildInputs = + (getPostgreSQLDeps false) + ++ [ + llvmPkgs.clang + llvmPkgs.lld + llvmPkgs.compiler-rt + flameGraphScript + pgbenchScript + ]; + + shellHook = let + icon = "f121"; + in '' + # History configuration + export HISTFILE=.history + export HISTSIZE=1000000 + export HISTFILESIZE=1000000 + + # Clean environment + unset LD_LIBRARY_PATH LD_PRELOAD LIBRARY_PATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH + + # Essential tools in PATH + export PATH="${pkgs.which}/bin:${pkgs.coreutils}/bin:$PATH" + export PS1="$(echo -e '\u${icon}') {\[$(tput sgr0)\]\[\033[38;5;228m\]\w\[$(tput sgr0)\]\[\033[38;5;15m\]} ($(git rev-parse --abbrev-ref HEAD)) \\$ \[$(tput sgr0)\]" + + # Ccache configuration + export PATH=${pkgs.ccache}/bin:$PATH + export CCACHE_COMPILERCHECK=content + export CCACHE_DIR=$HOME/.ccache_pg_dev_clang + mkdir -p "$CCACHE_DIR" + + # LLVM configuration + export LLVM_CONFIG="${llvmPkgs.llvm}/bin/llvm-config" + export PATH="${llvmPkgs.llvm}/bin:$PATH" + export PKG_CONFIG_PATH="${llvmPkgs.llvm.dev}/lib/pkgconfig:$PKG_CONFIG_PATH" + export LLVM_DIR="${llvmPkgs.llvm.dev}/lib/cmake/llvm" + export LLVM_ROOT="${llvmPkgs.llvm}" + + # Development tools in PATH + export PATH=${pkgs.clang-tools}/bin:$PATH + export PATH=${pkgs.cppcheck}/bin:$PATH + + # Clang + glibc configuration - use system linker instead of LLD for compatibility + export CC="${llvmPkgs.clang}/bin/clang" + export CXX="${llvmPkgs.clang}/bin/clang++" + + # Use system linker and standard runtime + #export CFLAGS="" + #export CXXFLAGS="" + #export LDFLAGS="" + + # PostgreSQL environment + export PG_SOURCE_DIR="${config.pgSourceDir}" + export PG_BUILD_DIR="${config.pgBuildDir}" + export PG_INSTALL_DIR="${config.pgInstallDir}" + export PG_DATA_DIR="${config.pgDataDir}" + export PG_BENCH_DIR="${config.pgBenchDir}" + export PG_FLAME_DIR="${config.pgFlameDir}" + export PERL_CORE_DIR=$(find ${pkgs.perl} -maxdepth 5 -path "*/CORE" -type d) + + # GDB configuration + export GDBINIT="${gdbConfig}" + + # Performance tools in PATH + export PATH="${flameGraphScript}/bin:${pgbenchScript}/bin:$PATH" + + # Create output directories + mkdir -p "$PG_BENCH_DIR" "$PG_FLAME_DIR" + + # Compiler verification + echo "Environment configured:" + echo " Compiler: $CC" + echo " libc: glibc" + echo " LLVM: $(llvm-config --version 2>/dev/null || echo 'not available')" + + # Load PostgreSQL development aliases + if [ -f ./pg-aliases.sh ]; then + source ./pg-aliases.sh + else + echo "Warning: pg-aliases.sh not found in current directory" + fi + + echo "" + echo "PostgreSQL Development Environment Ready (Clang + glibc)" + echo "Run 'pg-info' for available commands" + ''; + }; + + # GCC + musl variant (cross-compilation) + muslDevShell = pkgs.mkShell { + name = "postgresql-gcc-musl"; + buildInputs = + (getPostgreSQLDeps true) + ++ [ + pkgs.gcc + flameGraphScript + pgbenchScript + ]; + + shellHook = '' + # Same base configuration as main shell + export HISTFILE=.history + export HISTSIZE=1000000 + export HISTFILESIZE=1000000 + + unset LD_LIBRARY_PATH LD_PRELOAD LIBRARY_PATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH + + export PATH="${pkgs.which}/bin:${pkgs.coreutils}/bin:$PATH" + + # Cross-compilation to musl + export CC="${pkgs.gcc}/bin/gcc" + export CXX="${pkgs.gcc}/bin/g++" + + # Point to musl libraries for linking + export PKG_CONFIG_PATH="${pkgs.pkgsMusl.openssl.dev}/lib/pkgconfig:${pkgs.pkgsMusl.zlib.dev}/lib/pkgconfig:${pkgs.pkgsMusl.icu.dev}/lib/pkgconfig" + export CFLAGS="-ggdb -Og -fno-omit-frame-pointer -DUSE_VALGRIND -D_FORTIFY_SOURCE=1 -I${pkgs.pkgsMusl.stdenv.cc.libc}/include" + export CXXFLAGS="-ggdb -Og -fno-omit-frame-pointer -DUSE_VALGRIND -D_FORTIFY_SOURCE=1 -I${pkgs.pkgsMusl.stdenv.cc.libc}/include" + export LDFLAGS="-L${pkgs.pkgsMusl.stdenv.cc.libc}/lib -static-libgcc" + + # PostgreSQL environment + export PG_SOURCE_DIR="${config.pgSourceDir}" + export PG_BUILD_DIR="${config.pgBuildDir}" + export PG_INSTALL_DIR="${config.pgInstallDir}" + export PG_DATA_DIR="${config.pgDataDir}" + export PG_BENCH_DIR="${config.pgBenchDir}" + export PG_FLAME_DIR="${config.pgFlameDir}" + export PERL_CORE_DIR=$(find ${pkgs.perl} -maxdepth 5 -path "*/CORE" -type d) + + export GDBINIT="${gdbConfig}" + export PATH="${flameGraphScript}/bin:${pgbenchScript}/bin:$PATH" + + mkdir -p "$PG_BENCH_DIR" "$PG_FLAME_DIR" + + echo "GCC + musl environment configured" + echo " Compiler: $CC" + echo " LibC: musl (cross-compilation)" + + if [ -f ./pg-aliases.sh ]; then + source ./pg-aliases.sh + fi + + echo "PostgreSQL Development Environment Ready (GCC + musl)" + ''; + }; + + # Clang + musl variant (cross-compilation) + clangMuslDevShell = pkgs.mkShell { + name = "postgresql-clang-musl"; + buildInputs = + (getPostgreSQLDeps true) + ++ [ + llvmPkgs.clang + llvmPkgs.lld + flameGraphScript + pgbenchScript + ]; + + shellHook = let + icon = "f121"; + in '' + export HISTFILE=.history + export HISTSIZE=1000000 + export HISTFILESIZE=1000000 + + unset LD_LIBRARY_PATH LD_PRELOAD LIBRARY_PATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH + + export PATH="${pkgs.which}/bin:${pkgs.coreutils}/bin:$PATH" + export PS1="$(echo -e '\u${icon}') {\[$(tput sgr0)\]\[\033[38;5;228m\]\w\[$(tput sgr0)\]\[\033[38;5;15m\]} ($(git rev-parse --abbrev-ref HEAD)) \\$ \[$(tput sgr0)\]" + + # Cross-compilation to musl with clang + export CC="${llvmPkgs.clang}/bin/clang" + export CXX="${llvmPkgs.clang}/bin/clang++" + + # Point to musl libraries for linking + export PKG_CONFIG_PATH="${pkgs.pkgsMusl.openssl.dev}/lib/pkgconfig:${pkgs.pkgsMusl.zlib.dev}/lib/pkgconfig:${pkgs.pkgsMusl.icu.dev}/lib/pkgconfig" + export CFLAGS="--target=x86_64-linux-musl -ggdb -Og -fno-omit-frame-pointer -DUSE_VALGRIND -D_FORTIFY_SOURCE=1 -I${pkgs.pkgsMusl.stdenv.cc.libc}/include" + export CXXFLAGS="--target=x86_64-linux-musl -ggdb -Og -fno-omit-frame-pointer -DUSE_VALGRIND -D_FORTIFY_SOURCE=1 -I${pkgs.pkgsMusl.stdenv.cc.libc}/include" + export LDFLAGS="--target=x86_64-linux-musl -L${pkgs.pkgsMusl.stdenv.cc.libc}/lib -fuse-ld=lld" + + # PostgreSQL environment + export PG_SOURCE_DIR="${config.pgSourceDir}" + export PG_BUILD_DIR="${config.pgBuildDir}" + export PG_INSTALL_DIR="${config.pgInstallDir}" + export PG_DATA_DIR="${config.pgDataDir}" + export PG_BENCH_DIR="${config.pgBenchDir}" + export PG_FLAME_DIR="${config.pgFlameDir}" + export PERL_CORE_DIR=$(find ${pkgs.perl} -maxdepth 5 -path "*/CORE" -type d) + + export GDBINIT="${gdbConfig}" + export PATH="${flameGraphScript}/bin:${pgbenchScript}/bin:$PATH" + + mkdir -p "$PG_BENCH_DIR" "$PG_FLAME_DIR" + + echo "Clang + musl environment configured" + echo " Compiler: $CC" + echo " LibC: musl (cross-compilation)" + + if [ -f ./pg-aliases.sh ]; then + source ./pg-aliases.sh + fi + + echo "PostgreSQL Development Environment Ready (Clang + musl)" + ''; + }; +in { + inherit devShell clangDevShell muslDevShell clangMuslDevShell gdbConfig flameGraphScript pgbenchScript; +} diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 74a52d8706771..364f03b043eb5 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -1325,6 +1325,125 @@ heap_modify_tuple_by_cols(HeapTuple tuple, return newTuple; } +/* + * heap_update_tuple + * Form a new tuple from an old tuple and a set of replacement values. + * + * Creates a new HeapTuple by selectively replacing attributes from the original + * tuple with new values. The 'updated' Bitmapset specifies which attributes + * (by attribute number, 1-based adjusted by FirstLowInvalidHeapAttributeNumber) + * should be replaced with corresponding entries from new_values and new_isnull + * arrays (0-based indices). + * + * Performance strategy: + * - If updating many attributes (> 2*natts/3), use heap_getattr() to extract + * only the few non-updated attributes. This is O(k*n) where k is the number + * of non-updated attributes, which is small when updating many. + * - If updating few attributes (<= 2*natts/3), use heap_deform_tuple() to + * extract all attributes at once (O(n)), then replace the updated ones. + * This avoids the O(n^2) cost of many heap_getattr() calls. + * + * The threshold of 2*natts/3 balances the fixed O(n) cost of heap_deform_tuple + * against the variable O(k*n) cost of heap_getattr, where k = natts - num_updated. + */ +HeapTuple +heap_update_tuple(HeapTuple tuple, + TupleDesc desc, + const Datum *new_values, + const bool *new_nulls, + const Bitmapset *updated) +{ + int natts = desc->natts; + int num_updated; + Datum *values; + bool *nulls; + HeapTuple new_tuple; + + Assert(!bms_is_empty(updated)); + + num_updated = bms_num_members(updated); + Assert(num_updated <= natts); + + values = (Datum *) palloc0(natts * sizeof(Datum)); + nulls = (bool *) palloc0(natts * sizeof(bool)); + + /* + * Choose strategy based on update density. When updating most attributes, + * it's cheaper to extract the few unchanged ones individually. + */ + if (num_updated > (2 * natts) / 3) + { + /* Updating many: use heap_getattr for the few non-updated attributes */ + for (int i = 0; i < natts; i++) + { + /* + * Convert array index to attribute number, then to bitmapset + * member. Array index i (0-based) -> attnum (1-based) -> bms + * member. + */ + AttrNumber attnum = i + 1; + int member = attnum - FirstLowInvalidHeapAttributeNumber; + + if (bms_is_member(member, updated)) + { + /* Use replacement value */ + if (unlikely(!new_values || !new_nulls)) + values[i] = heap_getattr(tuple, attnum, desc, &nulls[i]); + + if (likely(new_values)) + values[i] = new_values[i]; + + if (likely(new_nulls)) + nulls[i] = new_nulls[i]; + } + else + { + /* Extract original value using heap_getattr (1-based) */ + values[i] = heap_getattr(tuple, attnum, desc, &nulls[i]); + } + } + } + else + { + int member = -1; + + /* Updating few: deform entire tuple, then replace updated attributes */ + heap_deform_tuple(tuple, desc, values, nulls); + + while ((member = bms_next_member(updated, member)) >= 0) + { + /* + * Convert bitmapset member to attribute number, then to array + * index. bms_member -> attnum (1-based) -> array index i + * (0-based). + */ + AttrNumber attnum = member + FirstLowInvalidHeapAttributeNumber; + int i = attnum - 1; + + Assert(i >= 0 && i < natts); + + if (likely(new_values)) + values[i] = new_values[i]; + + if (likely(new_nulls)) + nulls[i] = new_nulls[i]; + } + } + + /* Create the new tuple */ + new_tuple = heap_form_tuple(desc, values, nulls); + + pfree(values); + pfree(nulls); + + /* Preserve tuple identity and location information from the original */ + new_tuple->t_data->t_ctid = tuple->t_data->t_ctid; + new_tuple->t_self = tuple->t_self; + new_tuple->t_tableOid = tuple->t_tableOid; + + return new_tuple; +} + /* * heap_deform_tuple * Given a tuple, extract data into values/isnull arrays; this is diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index cd139bd65a668..3943d780a2219 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -1316,8 +1316,7 @@ SetDefaultACL(InternalDefaultACL *iacls) else { Datum values[Natts_pg_default_acl] = {0}; - bool nulls[Natts_pg_default_acl] = {0}; - bool replaces[Natts_pg_default_acl] = {0}; + bool nulls[Natts_pg_default_acl] = {false}; Oid defAclOid; if (isNew) @@ -1325,26 +1324,28 @@ SetDefaultACL(InternalDefaultACL *iacls) /* insert new entry */ defAclOid = GetNewOidWithIndex(rel, DefaultAclOidIndexId, Anum_pg_default_acl_oid); - values[Anum_pg_default_acl_oid - 1] = ObjectIdGetDatum(defAclOid); - values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid); - values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid); - values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype); - values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl); + HeapTupleSetValue(pg_default_acl, oid, ObjectIdGetDatum(defAclOid), values); + HeapTupleSetValue(pg_default_acl, defaclrole, ObjectIdGetDatum(iacls->roleid), values); + HeapTupleSetValue(pg_default_acl, defaclnamespace, ObjectIdGetDatum(iacls->nspid), values); + HeapTupleSetValue(pg_default_acl, defaclobjtype, CharGetDatum(objtype), values); + HeapTupleSetValue(pg_default_acl, defaclacl, PointerGetDatum(new_acl), values); newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, newtuple); + CatalogTupleInsert(rel, newtuple, NULL); } else { + Bitmapset *updated = NULL; + defAclOid = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid; /* update existing entry */ - values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl); - replaces[Anum_pg_default_acl_defaclacl - 1] = true; + HeapTupleUpdateValue(pg_default_acl, defaclacl, PointerGetDatum(new_acl), values, nulls, updated); + + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + bms_free(updated); } /* these dependencies don't change in an update */ @@ -1650,12 +1651,12 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, bool need_update; HeapTuple newtuple; Datum values[Natts_pg_attribute] = {0}; - bool nulls[Natts_pg_attribute] = {0}; - bool replaces[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; int noldmembers; int nnewmembers; Oid *oldmembers; Oid *newmembers; + Bitmapset *updated = NULL; attr_tuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(relOid), @@ -1742,22 +1743,21 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, */ if (ACL_NUM(new_acl) > 0) { - values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_attribute, attacl, PointerGetDatum(new_acl), values, nulls, updated); need_update = true; } else { - nulls[Anum_pg_attribute_attacl - 1] = true; + HeapTupleUpdateValueNull(pg_attribute, attacl, values, nulls, updated); need_update = !isNull; } - replaces[Anum_pg_attribute_attacl - 1] = true; if (need_update) { - newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation), - values, nulls, replaces); + newtuple = heap_update_tuple(attr_tuple, RelationGetDescr(attRelation), + values, nulls, updated); - CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple, updated, NULL); /* Update initial privileges for extensions */ recordExtensionInitPriv(relOid, RelationRelationId, attnum, @@ -1773,6 +1773,7 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname, pfree(new_acl); ReleaseSysCache(attr_tuple); + bms_free(updated); } /* @@ -1960,8 +1961,8 @@ ExecGrant_Relation(InternalGrant *istmt) Oid grantorId; HeapTuple newtuple; Datum values[Natts_pg_class] = {0}; - bool nulls[Natts_pg_class] = {0}; - bool replaces[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; int nnewmembers; Oid *newmembers; ObjectType objtype; @@ -2011,13 +2012,12 @@ ExecGrant_Relation(InternalGrant *istmt) nnewmembers = aclmembers(new_acl, &newmembers); /* finished building new ACL value, now insert it */ - replaces[Anum_pg_class_relacl - 1] = true; - values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_class, relacl, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), - values, nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); /* Update initial privileges for extensions */ @@ -2030,6 +2030,7 @@ ExecGrant_Relation(InternalGrant *istmt) nnewmembers, newmembers); pfree(new_acl); + bms_free(updated); } else UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); @@ -2140,7 +2141,7 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, HeapTuple newtuple; Datum *values = palloc0_array(Datum, RelationGetDescr(relation)->natts); bool *nulls = palloc0_array(bool, RelationGetDescr(relation)->natts); - bool *replaces = palloc0_array(bool, RelationGetDescr(relation)->natts); + Bitmapset *updated = NULL; int noldmembers; int nnewmembers; Oid *oldmembers; @@ -2214,14 +2215,17 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, */ nnewmembers = aclmembers(new_acl, &newmembers); - /* finished building new ACL value, now insert it */ - replaces[get_object_attnum_acl(classid) - 1] = true; + /* + * Finished building new ACL value, now insert it. NOTE: We can't use + * the HeapTupleMarkColumnUpdated() macro here because + * get_object_attnum_acl(classid) provides an index. + */ values[get_object_attnum_acl(classid) - 1] = PointerGetDatum(new_acl); + updated = bms_add_member(updated, get_object_attnum_acl(classid) - FirstLowInvalidHeapAttributeNumber); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, - nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); UnlockTuple(relation, &tuple->t_self, InplaceUpdateTupleLock); /* Update initial privileges for extensions */ @@ -2237,6 +2241,7 @@ ExecGrant_common(InternalGrant *istmt, Oid classid, AclMode default_privs, ReleaseSysCache(tuple); pfree(new_acl); + bms_free(updated); /* prevent error when processing duplicate objects */ CommandCounterIncrement(); @@ -2288,8 +2293,8 @@ ExecGrant_Largeobject(InternalGrant *istmt) Oid ownerId; HeapTuple newtuple; Datum values[Natts_pg_largeobject_metadata] = {0}; - bool nulls[Natts_pg_largeobject_metadata] = {0}; - bool replaces[Natts_pg_largeobject_metadata] = {0}; + bool nulls[Natts_pg_largeobject_metadata] = {false}; + Bitmapset *updated = NULL; int noldmembers; int nnewmembers; Oid *oldmembers; @@ -2367,14 +2372,12 @@ ExecGrant_Largeobject(InternalGrant *istmt) nnewmembers = aclmembers(new_acl, &newmembers); /* finished building new ACL value, now insert it */ - replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true; - values[Anum_pg_largeobject_metadata_lomacl - 1] - = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_largeobject_metadata, lomacl, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), - values, nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); /* Update initial privileges for extensions */ recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl); @@ -2389,6 +2392,7 @@ ExecGrant_Largeobject(InternalGrant *istmt) systable_endscan(scan); pfree(new_acl); + bms_free(updated); /* prevent error when processing duplicate objects */ CommandCounterIncrement(); @@ -2527,16 +2531,16 @@ ExecGrant_Parameter(InternalGrant *istmt) /* finished building new ACL value, now insert it */ HeapTuple newtuple; Datum values[Natts_pg_parameter_acl] = {0}; - bool nulls[Natts_pg_parameter_acl] = {0}; - bool replaces[Natts_pg_parameter_acl] = {0}; + bool nulls[Natts_pg_parameter_acl] = {false}; + Bitmapset *updated = NULL; - replaces[Anum_pg_parameter_acl_paracl - 1] = true; - values[Anum_pg_parameter_acl_paracl - 1] = PointerGetDatum(new_acl); + HeapTupleUpdateValue(pg_parameter_acl, paracl, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), - values, nulls, replaces); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); } /* Update initial privileges for extensions */ @@ -4667,8 +4671,8 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, if (HeapTupleIsValid(oldtuple)) { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; - bool replace[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; + Bitmapset *updated = NULL; Datum oldAclDatum; bool isNull; Acl *old_acl; @@ -4687,13 +4691,13 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, /* If we have a new ACL to set, then update the row with it. */ if (new_acl && ACL_NUM(new_acl) != 0) { - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); - replace[Anum_pg_init_privs_initprivs - 1] = true; + HeapTupleUpdateValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values, nulls, updated); - oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation), - values, nulls, replace); + oldtuple = heap_update_tuple(oldtuple, RelationGetDescr(relation), + values, nulls, updated); - CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple); + CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple, updated, NULL); + bms_free(updated); } else { @@ -4704,7 +4708,7 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, else { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; /* * Only add a new entry if the new ACL is non-NULL. @@ -4715,19 +4719,18 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, if (new_acl && ACL_NUM(new_acl) != 0) { /* No entry found, so add it. */ - values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid); - values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid); - values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid); + HeapTupleSetValue(pg_init_privs, objoid, ObjectIdGetDatum(objoid), values); + HeapTupleSetValue(pg_init_privs, classoid, ObjectIdGetDatum(classoid), values); + HeapTupleSetValue(pg_init_privs, objsubid, Int32GetDatum(objsubid), values); /* This function only handles initial privileges of extensions */ - values[Anum_pg_init_privs_privtype - 1] = - CharGetDatum(INITPRIVS_EXTENSION); + HeapTupleSetValue(pg_init_privs, privtype, CharGetDatum(INITPRIVS_EXTENSION), values); - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); + HeapTupleSetValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values); tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls); - CatalogTupleInsert(relation, tuple); + CatalogTupleInsert(relation, tuple, NULL); /* Update pg_shdepend, too. */ noldmembers = 0; @@ -4826,16 +4829,16 @@ ReplaceRoleInInitPriv(Oid oldroleid, Oid newroleid, else { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; - bool replaces[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; + Bitmapset *updated = NULL; /* Update existing entry. */ - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); - replaces[Anum_pg_init_privs_initprivs - 1] = true; + HeapTupleUpdateValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values, nulls, updated); - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(rel), + values, nulls, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); } /* @@ -4962,16 +4965,16 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid) else { Datum values[Natts_pg_init_privs] = {0}; - bool nulls[Natts_pg_init_privs] = {0}; - bool replaces[Natts_pg_init_privs] = {0}; + bool nulls[Natts_pg_init_privs] = {false}; + Bitmapset *updated2 = NULL; /* Update existing entry. */ - values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl); - replaces[Anum_pg_init_privs_initprivs - 1] = true; + HeapTupleUpdateValue(pg_init_privs, initprivs, PointerGetDatum(new_acl), values, nulls, updated2); - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(rel), + values, nulls, updated2); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated2, NULL); + bms_free(updated2); } /* diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index fd6537567ea27..a70d61c8f6b54 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -30,6 +30,7 @@ #include "postgres.h" #include "access/genam.h" +#include "access/htup.h" #include "access/multixact.h" #include "access/relation.h" #include "access/table.h" @@ -705,7 +706,7 @@ CheckAttributeType(const char *attname, * 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 + * indstate is the index state for CatalogTupleInsert. It can be * passed as NULL, in which case we'll fetch the necessary info. (Don't do * this when inserting multiple attributes, because it's a tad more * expensive.) @@ -720,7 +721,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, const FormExtraData_pg_attribute tupdesc_extra[], CatalogIndexState indstate) { - TupleTableSlot **slot; + TupleTableSlot **slots; TupleDesc td; int nslots; int natts = 0; @@ -732,66 +733,70 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, /* Initialize the number of slots to use */ nslots = Min(tupdesc->natts, (MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_attribute))); - slot = palloc(sizeof(TupleTableSlot *) * nslots); + slots = palloc(sizeof(TupleTableSlot *) * nslots); for (int i = 0; i < nslots; i++) - slot[i] = MakeSingleTupleTableSlot(td, &TTSOpsHeapTuple); + slots[i] = MakeSingleTupleTableSlot(td, &TTSOpsHeapTuple); while (natts < tupdesc->natts) { + TupleTableSlot *slot = slots[slotCount]; + Datum *values = slot->tts_values; Form_pg_attribute attrs = TupleDescAttr(tupdesc, natts); const FormExtraData_pg_attribute *attrs_extra = tupdesc_extra ? &tupdesc_extra[natts] : NULL; - ExecClearTuple(slot[slotCount]); + ExecClearTuple(slot); - memset(slot[slotCount]->tts_isnull, false, - slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool)); + memset(slot->tts_isnull, false, + slot->tts_tupleDescriptor->natts * sizeof(bool)); if (new_rel_oid != InvalidOid) - slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_rel_oid); + HeapTupleSetValue(pg_attribute, attrelid, ObjectIdGetDatum(new_rel_oid), values); else - slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(attrs->attrelid); - - slot[slotCount]->tts_values[Anum_pg_attribute_attname - 1] = NameGetDatum(&attrs->attname); - 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_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); - slot[slotCount]->tts_values[Anum_pg_attribute_attalign - 1] = CharGetDatum(attrs->attalign); - slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage); - slot[slotCount]->tts_values[Anum_pg_attribute_attcompression - 1] = CharGetDatum(attrs->attcompression); - slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(attrs->attnotnull); - slot[slotCount]->tts_values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(attrs->atthasdef); - slot[slotCount]->tts_values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(attrs->atthasmissing); - slot[slotCount]->tts_values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(attrs->attidentity); - slot[slotCount]->tts_values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(attrs->attgenerated); - slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped); - slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal); - slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int16GetDatum(attrs->attinhcount); - slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation); + HeapTupleSetValue(pg_attribute, attrelid, ObjectIdGetDatum(attrs->attrelid), values); + + HeapTupleSetValue(pg_attribute, attname, NameGetDatum(&attrs->attname), values); + HeapTupleSetValue(pg_attribute, atttypid, ObjectIdGetDatum(attrs->atttypid), values); + HeapTupleSetValue(pg_attribute, attlen, Int16GetDatum(attrs->attlen), values); + HeapTupleSetValue(pg_attribute, attnum, Int16GetDatum(attrs->attnum), values); + HeapTupleSetValue(pg_attribute, atttypmod, Int32GetDatum(attrs->atttypmod), values); + HeapTupleSetValue(pg_attribute, attndims, Int16GetDatum(attrs->attndims), values); + HeapTupleSetValue(pg_attribute, attbyval, BoolGetDatum(attrs->attbyval), values); + HeapTupleSetValue(pg_attribute, attalign, CharGetDatum(attrs->attalign), values); + HeapTupleSetValue(pg_attribute, attstorage, CharGetDatum(attrs->attstorage), values); + HeapTupleSetValue(pg_attribute, attcompression, CharGetDatum(attrs->attcompression), values); + HeapTupleSetValue(pg_attribute, attnotnull, BoolGetDatum(attrs->attnotnull), values); + HeapTupleSetValue(pg_attribute, atthasdef, BoolGetDatum(attrs->atthasdef), values); + HeapTupleSetValue(pg_attribute, atthasmissing, BoolGetDatum(attrs->atthasmissing), values); + HeapTupleSetValue(pg_attribute, attidentity, CharGetDatum(attrs->attidentity), values); + HeapTupleSetValue(pg_attribute, attgenerated, CharGetDatum(attrs->attgenerated), values); + HeapTupleSetValue(pg_attribute, attisdropped, BoolGetDatum(attrs->attisdropped), values); + HeapTupleSetValue(pg_attribute, attislocal, BoolGetDatum(attrs->attislocal), values); + HeapTupleSetValue(pg_attribute, attinhcount, Int16GetDatum(attrs->attinhcount), values); + HeapTupleSetValue(pg_attribute, attcollation, ObjectIdGetDatum(attrs->attcollation), values); if (attrs_extra) { - slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.value; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = attrs_extra->attstattarget.isnull; + HeapTupleSetValue(pg_attribute, attstattarget, attrs_extra->attstattarget.value, values); + if (attrs_extra->attstattarget.isnull) + HeapTupleSetValueNull(pg_attribute, attstattarget, values, slot->tts_isnull); - slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.value; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = attrs_extra->attoptions.isnull; + HeapTupleSetValue(pg_attribute, attoptions, attrs_extra->attoptions.value, values); + if (attrs_extra->attoptions.isnull) + HeapTupleSetValueNull(pg_attribute, attoptions, values, slot->tts_isnull); } else { - slot[slotCount]->tts_isnull[Anum_pg_attribute_attstattarget - 1] = true; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true; + HeapTupleSetValueNull(pg_attribute, attstattarget, values, slot->tts_isnull); + HeapTupleSetValueNull(pg_attribute, attoptions, values, slot->tts_isnull); } /* * The remaining fields are not set for new columns. */ - slot[slotCount]->tts_isnull[Anum_pg_attribute_attacl - 1] = true; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attfdwoptions - 1] = true; - slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true; + HeapTupleSetValueNull(pg_attribute, attacl, values, slot->tts_isnull); + HeapTupleSetValueNull(pg_attribute, attfdwoptions, values, slot->tts_isnull); + HeapTupleSetValueNull(pg_attribute, attmissingval, values, slot->tts_isnull); - ExecStoreVirtualTuple(slot[slotCount]); + ExecStoreVirtualTuple(slot); slotCount++; /* @@ -808,8 +813,7 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, } /* insert the new tuples and update the indexes */ - CatalogTuplesMultiInsertWithInfo(pg_attribute_rel, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(pg_attribute_rel, slots, slotCount, indstate); slotCount = 0; } @@ -819,8 +823,8 @@ InsertPgAttributeTuples(Relation pg_attribute_rel, if (close_index) CatalogCloseIndexes(indstate); for (int i = 0; i < nslots; i++) - ExecDropSingleTupleTableSlot(slot[i]); - pfree(slot); + ExecDropSingleTupleTableSlot(slots[i]); + pfree(slots); } /* -------------------------------- @@ -914,61 +918,58 @@ InsertPgClassTuple(Relation pg_class_desc, Datum reloptions) { Form_pg_class rd_rel = new_rel_desc->rd_rel; - Datum values[Natts_pg_class]; - bool nulls[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; HeapTuple tup; /* This is a tad tedious, but way cleaner than what we used to do... */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - - values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid); - values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname); - values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace); - values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype); - values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype); - values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner); - values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam); - values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode); - values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace); - 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); - values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence); - values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind); - values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts); - values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks); - values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules); - values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers); - values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity); - values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity); - values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass); - values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated); - values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident); - values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition); - values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite); - values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid); - values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid); + HeapTupleSetValue(pg_class, oid, ObjectIdGetDatum(new_rel_oid), values); + HeapTupleSetValue(pg_class, relname, NameGetDatum(&rd_rel->relname), values); + HeapTupleSetValue(pg_class, relnamespace, ObjectIdGetDatum(rd_rel->relnamespace), values); + HeapTupleSetValue(pg_class, reltype, ObjectIdGetDatum(rd_rel->reltype), values); + HeapTupleSetValue(pg_class, reloftype, ObjectIdGetDatum(rd_rel->reloftype), values); + HeapTupleSetValue(pg_class, relowner, ObjectIdGetDatum(rd_rel->relowner), values); + HeapTupleSetValue(pg_class, relam, ObjectIdGetDatum(rd_rel->relam), values); + HeapTupleSetValue(pg_class, relfilenode, ObjectIdGetDatum(rd_rel->relfilenode), values); + HeapTupleSetValue(pg_class, reltablespace, ObjectIdGetDatum(rd_rel->reltablespace), values); + HeapTupleSetValue(pg_class, relpages, Int32GetDatum(rd_rel->relpages), values); + HeapTupleSetValue(pg_class, reltuples, Float4GetDatum(rd_rel->reltuples), values); + HeapTupleSetValue(pg_class, relallvisible, Int32GetDatum(rd_rel->relallvisible), values); + HeapTupleSetValue(pg_class, relallfrozen, Int32GetDatum(rd_rel->relallfrozen), values); + HeapTupleSetValue(pg_class, reltoastrelid, ObjectIdGetDatum(rd_rel->reltoastrelid), values); + HeapTupleSetValue(pg_class, relhasindex, BoolGetDatum(rd_rel->relhasindex), values); + HeapTupleSetValue(pg_class, relisshared, BoolGetDatum(rd_rel->relisshared), values); + HeapTupleSetValue(pg_class, relpersistence, CharGetDatum(rd_rel->relpersistence), values); + HeapTupleSetValue(pg_class, relkind, CharGetDatum(rd_rel->relkind), values); + HeapTupleSetValue(pg_class, relnatts, Int16GetDatum(rd_rel->relnatts), values); + HeapTupleSetValue(pg_class, relchecks, Int16GetDatum(rd_rel->relchecks), values); + HeapTupleSetValue(pg_class, relhasrules, BoolGetDatum(rd_rel->relhasrules), values); + HeapTupleSetValue(pg_class, relhastriggers, BoolGetDatum(rd_rel->relhastriggers), values); + HeapTupleSetValue(pg_class, relrowsecurity, BoolGetDatum(rd_rel->relrowsecurity), values); + HeapTupleSetValue(pg_class, relforcerowsecurity, BoolGetDatum(rd_rel->relforcerowsecurity), values); + HeapTupleSetValue(pg_class, relhassubclass, BoolGetDatum(rd_rel->relhassubclass), values); + HeapTupleSetValue(pg_class, relispopulated, BoolGetDatum(rd_rel->relispopulated), values); + HeapTupleSetValue(pg_class, relreplident, CharGetDatum(rd_rel->relreplident), values); + HeapTupleSetValue(pg_class, relispartition, BoolGetDatum(rd_rel->relispartition), values); + HeapTupleSetValue(pg_class, relrewrite, ObjectIdGetDatum(rd_rel->relrewrite), values); + HeapTupleSetValue(pg_class, relfrozenxid, TransactionIdGetDatum(rd_rel->relfrozenxid), values); + HeapTupleSetValue(pg_class, relminmxid, MultiXactIdGetDatum(rd_rel->relminmxid), values); if (relacl != (Datum) 0) - values[Anum_pg_class_relacl - 1] = relacl; + HeapTupleSetValue(pg_class, relacl, relacl, values); else - nulls[Anum_pg_class_relacl - 1] = true; + HeapTupleSetValueNull(pg_class, relacl, values, nulls); if (reloptions != (Datum) 0) - values[Anum_pg_class_reloptions - 1] = reloptions; + HeapTupleSetValue(pg_class, reloptions, reloptions, values); else - nulls[Anum_pg_class_reloptions - 1] = true; + HeapTupleSetValueNull(pg_class, reloptions, values, nulls); /* relpartbound is set by updating this tuple, if necessary */ - nulls[Anum_pg_class_relpartbound - 1] = true; + HeapTupleSetValueNull(pg_class, relpartbound, values, nulls); tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls); /* finally insert the new tuple, update the indexes, and clean up */ - CatalogTupleInsert(pg_class_desc, tup); + CatalogTupleInsert(pg_class_desc, tup, NULL); heap_freetuple(tup); } @@ -1687,9 +1688,8 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) HeapTuple tuple; Form_pg_attribute attStruct; char newattname[NAMEDATALEN]; - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; /* * Grab an exclusive lock on the target table, which we will NOT release @@ -1710,7 +1710,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) attStruct = (Form_pg_attribute) GETSTRUCT(tuple); /* Mark the attribute as dropped */ - attStruct->attisdropped = true; + HeapTupleUpdateField(pg_attribute, attisdropped, true, attStruct, updated); /* * Set the type OID to invalid. A dropped attribute's type link cannot be @@ -1720,13 +1720,13 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) * the attribute's attlen and attalign. We set atttypid to zero here as a * means of catching code that incorrectly expects it to be valid. */ - attStruct->atttypid = InvalidOid; + HeapTupleUpdateField(pg_attribute, atttypid, InvalidOid, attStruct, updated); /* Remove any not-null constraint the column may have */ - attStruct->attnotnull = false; + HeapTupleUpdateField(pg_attribute, attnotnull, false, attStruct, updated); /* Unset this so no one tries to look up the generation expression */ - attStruct->attgenerated = '\0'; + HeapTupleUpdateField(pg_attribute, attgenerated, '\0', attStruct, updated); /* * Change the column name to something that isn't likely to conflict @@ -1734,29 +1734,33 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) snprintf(newattname, sizeof(newattname), "........pg.dropped.%d........", attnum); namestrcpy(&(attStruct->attname), newattname); + HeapTupleMarkColumnUpdated(pg_attribute, attname, updated); /* Clear the missing value */ - attStruct->atthasmissing = false; - nullsAtt[Anum_pg_attribute_attmissingval - 1] = true; - replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; + HeapTupleUpdateField(pg_attribute, atthasmissing, false, attStruct, updated); + HeapTupleSetFieldNull(pg_attribute, attmissingval, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attmissingval, updated); /* * Clear the other nullable fields. This saves some space in pg_attribute * and removes no longer useful information. */ - nullsAtt[Anum_pg_attribute_attstattarget - 1] = true; - replacesAtt[Anum_pg_attribute_attstattarget - 1] = true; - nullsAtt[Anum_pg_attribute_attacl - 1] = true; - replacesAtt[Anum_pg_attribute_attacl - 1] = true; - nullsAtt[Anum_pg_attribute_attoptions - 1] = true; - replacesAtt[Anum_pg_attribute_attoptions - 1] = true; - nullsAtt[Anum_pg_attribute_attfdwoptions - 1] = true; - replacesAtt[Anum_pg_attribute_attfdwoptions - 1] = true; + HeapTupleSetFieldNull(pg_attribute, attstattarget, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attstattarget, updated); - tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel), - valuesAtt, nullsAtt, replacesAtt); + HeapTupleSetFieldNull(pg_attribute, attacl, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attacl, updated); - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleSetFieldNull(pg_attribute, attoptions, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attoptions, updated); + + HeapTupleSetFieldNull(pg_attribute, attfdwoptions, nulls); + HeapTupleMarkColumnUpdated(pg_attribute, attfdwoptions, updated); + + tuple = heap_update_tuple(tuple, RelationGetDescr(attr_rel), + NULL, nulls, updated); + + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); /* * Because updating the pg_attribute row will trigger a relcache flush for @@ -1765,10 +1769,9 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) */ table_close(attr_rel, RowExclusiveLock); - RemoveStatistics(relid, attnum); - relation_close(rel, NoLock); + bms_free(updated); } /* @@ -1967,23 +1970,15 @@ RelationClearMissing(Relation rel) Oid relid = RelationGetRelid(rel); int natts = RelationGetNumberOfAttributes(rel); int attnum; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Form_pg_attribute attrtuple; HeapTuple tuple, newtuple; - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false); - repl_null[Anum_pg_attribute_attmissingval - 1] = true; - - repl_repl[Anum_pg_attribute_atthasmissing - 1] = true; - repl_repl[Anum_pg_attribute_attmissingval - 1] = true; - + HeapTupleUpdateValue(pg_attribute, atthasmissing, BoolGetDatum(false), values, nulls, updated); + HeapTupleUpdateValueNull(pg_attribute, attmissingval, values, nulls, updated); /* Get a lock on pg_attribute */ attr_rel = table_open(AttributeRelationId, RowExclusiveLock); @@ -2003,10 +1998,10 @@ RelationClearMissing(Relation rel) /* ignore any where atthasmissing is not true */ if (attrtuple->atthasmissing) { - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel), - repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tuple, RelationGetDescr(attr_rel), + values, nulls, updated); - CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); } @@ -2019,6 +2014,7 @@ RelationClearMissing(Relation rel) * there's nothing else to do here. */ table_close(attr_rel, RowExclusiveLock); + bms_free(updated); } /* @@ -2029,9 +2025,9 @@ RelationClearMissing(Relation rel) 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}; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Relation attrrel; Form_pg_attribute attStruct; HeapTuple atttup, @@ -2060,17 +2056,15 @@ StoreAttrMissingVal(Relation rel, AttrNumber attnum, Datum missingval) 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; + HeapTupleUpdateValue(pg_attribute, atthasmissing, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_attribute, attmissingval, missingval, values, nulls, updated); - newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), - valuesAtt, nullsAtt, replacesAtt); - CatalogTupleUpdate(attrrel, &newtup->t_self, newtup); + newtup = heap_update_tuple(atttup, RelationGetDescr(attrrel), + values, nulls, updated); + CatalogTupleUpdate(attrrel, &newtup->t_self, newtup, updated, NULL); /* clean up */ + bms_free(updated); ReleaseSysCache(atttup); table_close(attrrel, RowExclusiveLock); } @@ -2085,9 +2079,9 @@ StoreAttrMissingVal(Relation rel, AttrNumber attnum, Datum missingval) void SetAttrMissing(Oid relid, char *attname, char *value) { - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Datum missingval; Form_pg_attribute attStruct; Relation attrrel, @@ -2120,16 +2114,15 @@ SetAttrMissing(Oid relid, char *attname, char *value) Int32GetDatum(attStruct->atttypmod)); /* update the tuple - set atthasmissing and attmissingval */ - 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; + HeapTupleUpdateValue(pg_attribute, atthasmissing, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_attribute, attmissingval, missingval, values, nulls, updated); - newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel), - valuesAtt, nullsAtt, replacesAtt); - CatalogTupleUpdate(attrrel, &newtup->t_self, newtup); + newtup = heap_update_tuple(atttup, RelationGetDescr(attrrel), + values, nulls, updated); + CatalogTupleUpdate(attrrel, &newtup->t_self, newtup, updated, NULL); /* clean up */ + bms_free(updated); ReleaseSysCache(atttup); table_close(attrrel, RowExclusiveLock); table_close(tablerel, AccessExclusiveLock); @@ -2719,6 +2712,7 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, SysScanDesc conscan; ScanKeyData skey[3]; HeapTuple tup; + Bitmapset *updated = NULL; /* Search for a pg_constraint entry with same name and relation */ conDesc = table_open(ConstraintRelationId, RowExclusiveLock); @@ -2834,24 +2828,25 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, */ if (rel->rd_rel->relispartition) { - con->coninhcount = 1; - con->conislocal = false; + HeapTupleUpdateField(pg_constraint, coninhcount, 1, con, updated); + HeapTupleUpdateField(pg_constraint, conislocal, false, con, updated); } else { if (is_local) - con->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, con, updated); else if (pg_add_s16_overflow(con->coninhcount, 1, &con->coninhcount)) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleUpdateField(pg_constraint, coninhcount, con->coninhcount, con, updated); } if (is_no_inherit) { Assert(is_local); - con->connoinherit = true; + HeapTupleUpdateField(pg_constraint, connoinherit, true, con, updated); } /* @@ -2863,11 +2858,12 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, if (is_enforced && !con->conenforced) { Assert(is_local); - con->conenforced = true; - con->convalidated = true; + HeapTupleUpdateField(pg_constraint, conenforced, true, con, updated); + HeapTupleUpdateField(pg_constraint, convalidated, true, con, updated); } - CatalogTupleUpdate(conDesc, &tup->t_self, tup); + CatalogTupleUpdate(conDesc, &tup->t_self, tup, updated, NULL); + bms_free(updated); } systable_endscan(conscan); @@ -3148,6 +3144,7 @@ SetRelationNumChecks(Relation rel, int numchecks) Relation relrel; HeapTuple reltup; Form_pg_class relStruct; + Bitmapset *updated = NULL; relrel = table_open(RelationRelationId, RowExclusiveLock); reltup = SearchSysCacheCopy1(RELOID, @@ -3159,9 +3156,10 @@ SetRelationNumChecks(Relation rel, int numchecks) if (relStruct->relchecks != numchecks) { - relStruct->relchecks = numchecks; + HeapTupleUpdateField(pg_class, relchecks, numchecks, relStruct, updated); - CatalogTupleUpdate(relrel, &reltup->t_self, reltup); + CatalogTupleUpdate(relrel, &reltup->t_self, reltup, updated, NULL); + bms_free(updated); } else { @@ -3470,7 +3468,7 @@ CopyStatistics(Oid fromrelid, Oid torelid) if (indstate == NULL) indstate = CatalogOpenIndexes(statrel); - CatalogTupleInsertWithInfo(statrel, tup, indstate); + CatalogTupleInsert(statrel, tup, indstate); heap_freetuple(tup); } @@ -3906,8 +3904,8 @@ StorePartitionKey(Relation rel, Datum partexprDatum; Relation pg_partitioned_table; HeapTuple tuple; - Datum values[Natts_pg_partitioned_table]; - bool nulls[Natts_pg_partitioned_table] = {0}; + Datum values[Natts_pg_partitioned_table] = {0}; + bool nulls[Natts_pg_partitioned_table] = {false}; ObjectAddress myself; ObjectAddress referenced; ObjectAddresses *addrs; @@ -3935,20 +3933,20 @@ StorePartitionKey(Relation rel, /* Only this can ever be NULL */ if (!partexprDatum) - nulls[Anum_pg_partitioned_table_partexprs - 1] = true; + HeapTupleSetValueNull(pg_partitioned_table, partexprs, values, nulls); - values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); - values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy); - values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts); - values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec); - values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec); - values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec); - values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum; + HeapTupleSetValue(pg_partitioned_table, partrelid, ObjectIdGetDatum(RelationGetRelid(rel)), values); + HeapTupleSetValue(pg_partitioned_table, partstrat, CharGetDatum(strategy), values); + HeapTupleSetValue(pg_partitioned_table, partnatts, Int16GetDatum(partnatts), values); + HeapTupleSetValue(pg_partitioned_table, partdefid, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_partitioned_table, partattrs, PointerGetDatum(partattrs_vec), values); + HeapTupleSetValue(pg_partitioned_table, partclass, PointerGetDatum(partopclass_vec), values); + HeapTupleSetValue(pg_partitioned_table, partcollation, PointerGetDatum(partcollation_vec), values); + HeapTupleSetValue(pg_partitioned_table, partexprs, partexprDatum, values); tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls); - CatalogTupleInsert(pg_partitioned_table, tuple); + CatalogTupleInsert(pg_partitioned_table, tuple, NULL); table_close(pg_partitioned_table, RowExclusiveLock); /* Mark this relation as dependent on a few things as follows */ @@ -4052,9 +4050,9 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound) Relation classRel; HeapTuple tuple, newtuple; - Datum new_val[Natts_pg_class]; - bool new_null[Natts_pg_class], - new_repl[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; Oid defaultPartOid; /* Update pg_class tuple */ @@ -4065,12 +4063,14 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound) elog(ERROR, "cache lookup failed for relation %u", RelationGetRelid(rel)); + #ifdef USE_ASSERT_CHECKING { Form_pg_class classForm; bool isnull; classForm = (Form_pg_class) GETSTRUCT(tuple); + Assert(!classForm->relispartition); (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound, &isnull); @@ -4079,26 +4079,23 @@ StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound) #endif /* Fill in relpartbound value */ - memset(new_val, 0, sizeof(new_val)); - memset(new_null, false, sizeof(new_null)); - memset(new_repl, false, sizeof(new_repl)); - new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound)); - new_null[Anum_pg_class_relpartbound - 1] = false; - new_repl[Anum_pg_class_relpartbound - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel), - new_val, new_null, new_repl); + HeapTupleUpdateValue(pg_class, relpartbound, CStringGetTextDatum(nodeToString(bound)), values, nulls, updated); + newtuple = heap_update_tuple(tuple, RelationGetDescr(classRel), + values, nulls, updated); + /* Also set the flag */ - ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true; + HeapTupleUpdateField(pg_class, relispartition, true, (Form_pg_class) GETSTRUCT(newtuple), updated); /* * We already checked for no inheritance children, but reset * relhassubclass in case it was left over. */ if (rel->rd_rel->relkind == RELKIND_RELATION && rel->rd_rel->relhassubclass) - ((Form_pg_class) GETSTRUCT(newtuple))->relhassubclass = false; + HeapTupleUpdateField(pg_class, relhassubclass, false, (Form_pg_class) GETSTRUCT(newtuple), updated); - CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); + bms_free(updated); table_close(classRel, RowExclusiveLock); /* diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 5d9db167e5950..31e78342d63f8 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -579,8 +579,8 @@ UpdateIndexRelation(Oid indexoid, int2vector *indoption; Datum exprsDatum; Datum predDatum; - Datum values[Natts_pg_index]; - bool nulls[Natts_pg_index] = {0}; + Datum values[Natts_pg_index] = {0}; + bool nulls[Natts_pg_index] = {false}; Relation pg_index; HeapTuple tuple; int i; @@ -634,38 +634,38 @@ UpdateIndexRelation(Oid indexoid, /* * Build a pg_index tuple */ - values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid); - values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid); - values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs); - values[Anum_pg_index_indnkeyatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs); - values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique); - values[Anum_pg_index_indnullsnotdistinct - 1] = BoolGetDatum(indexInfo->ii_NullsNotDistinct); - values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary); - values[Anum_pg_index_indisexclusion - 1] = BoolGetDatum(isexclusion); - values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate); - values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false); - values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid); - values[Anum_pg_index_indcheckxmin - 1] = BoolGetDatum(false); - values[Anum_pg_index_indisready - 1] = BoolGetDatum(isready); - values[Anum_pg_index_indislive - 1] = BoolGetDatum(true); - values[Anum_pg_index_indisreplident - 1] = BoolGetDatum(false); - values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey); - values[Anum_pg_index_indcollation - 1] = PointerGetDatum(indcollation); - values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass); - values[Anum_pg_index_indoption - 1] = PointerGetDatum(indoption); - values[Anum_pg_index_indexprs - 1] = exprsDatum; + HeapTupleSetValue(pg_index, indexrelid, ObjectIdGetDatum(indexoid), values); + HeapTupleSetValue(pg_index, indrelid, ObjectIdGetDatum(heapoid), values); + HeapTupleSetValue(pg_index, indnatts, Int16GetDatum(indexInfo->ii_NumIndexAttrs), values); + HeapTupleSetValue(pg_index, indnkeyatts, Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs), values); + HeapTupleSetValue(pg_index, indisunique, BoolGetDatum(indexInfo->ii_Unique), values); + HeapTupleSetValue(pg_index, indnullsnotdistinct, BoolGetDatum(indexInfo->ii_NullsNotDistinct), values); + HeapTupleSetValue(pg_index, indisprimary, BoolGetDatum(primary), values); + HeapTupleSetValue(pg_index, indisexclusion, BoolGetDatum(isexclusion), values); + HeapTupleSetValue(pg_index, indimmediate, BoolGetDatum(immediate), values); + HeapTupleSetValue(pg_index, indisclustered, BoolGetDatum(false), values); + HeapTupleSetValue(pg_index, indisvalid, BoolGetDatum(isvalid), values); + HeapTupleSetValue(pg_index, indcheckxmin, BoolGetDatum(false), values); + HeapTupleSetValue(pg_index, indisready, BoolGetDatum(isready), values); + HeapTupleSetValue(pg_index, indislive, BoolGetDatum(true), values); + HeapTupleSetValue(pg_index, indisreplident, BoolGetDatum(false), values); + HeapTupleSetValue(pg_index, indkey, PointerGetDatum(indkey), values); + HeapTupleSetValue(pg_index, indcollation, PointerGetDatum(indcollation), values); + HeapTupleSetValue(pg_index, indclass, PointerGetDatum(indclass), values); + HeapTupleSetValue(pg_index, indoption, PointerGetDatum(indoption), values); + HeapTupleSetValue(pg_index, indexprs, exprsDatum, values); if (exprsDatum == (Datum) 0) - nulls[Anum_pg_index_indexprs - 1] = true; - values[Anum_pg_index_indpred - 1] = predDatum; + HeapTupleSetValueNull(pg_index, indexprs, values, nulls); + HeapTupleSetValue(pg_index, indpred, predDatum, values); if (predDatum == (Datum) 0) - nulls[Anum_pg_index_indpred - 1] = true; + HeapTupleSetValueNull(pg_index, indpred, values, nulls); tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls); /* * insert the tuple into the pg_index catalog */ - CatalogTupleInsert(pg_index, tuple); + CatalogTupleInsert(pg_index, tuple, NULL); /* * close the relation and free the tuple @@ -1569,6 +1569,8 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) Oid indexConstraintOid; List *constraintOids = NIL; ListCell *lc; + Bitmapset *oldUpdated = NULL; + Bitmapset *newUpdated = NULL; /* * Take a necessary lock on the old and new index before swapping them. @@ -1594,14 +1596,21 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) /* Swap the names */ namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname)); namestrcpy(&oldClassForm->relname, oldName); + HeapTupleUpdateField(pg_class, relname, newClassForm->relname, newClassForm, newUpdated); + HeapTupleUpdateField(pg_class, relname, oldClassForm->relname, oldClassForm, oldUpdated); /* Swap the partition flags to track inheritance properly */ isPartition = newClassForm->relispartition; - newClassForm->relispartition = oldClassForm->relispartition; - oldClassForm->relispartition = isPartition; + HeapTupleUpdateField(pg_class, relispartition, oldClassForm->relispartition, newClassForm, newUpdated); + HeapTupleUpdateField(pg_class, relispartition, isPartition, oldClassForm, oldUpdated); - CatalogTupleUpdate(pg_class, &oldClassTuple->t_self, oldClassTuple); - CatalogTupleUpdate(pg_class, &newClassTuple->t_self, newClassTuple); + CatalogTupleUpdate(pg_class, &oldClassTuple->t_self, oldClassTuple, oldUpdated, NULL); + CatalogTupleUpdate(pg_class, &newClassTuple->t_self, newClassTuple, newUpdated, NULL); + + bms_free(oldUpdated); + oldUpdated = NULL; + bms_free(newUpdated); + newUpdated = NULL; heap_freetuple(oldClassTuple); heap_freetuple(newClassTuple); @@ -1625,34 +1634,39 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) * Copy constraint flags from the old index. This is safe because the old * index guaranteed uniqueness. */ - newIndexForm->indisprimary = oldIndexForm->indisprimary; - oldIndexForm->indisprimary = false; - newIndexForm->indisexclusion = oldIndexForm->indisexclusion; - oldIndexForm->indisexclusion = false; - newIndexForm->indimmediate = oldIndexForm->indimmediate; - oldIndexForm->indimmediate = true; + HeapTupleUpdateField(pg_index, indisprimary, oldIndexForm->indisprimary, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indisprimary, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indisexclusion, oldIndexForm->indisexclusion, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indisexclusion, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indimmediate, oldIndexForm->indimmediate, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indimmediate, true, oldIndexForm, oldUpdated); /* Preserve indisreplident in the new index */ - newIndexForm->indisreplident = oldIndexForm->indisreplident; + HeapTupleUpdateField(pg_index, indisreplident, oldIndexForm->indisreplident, newIndexForm, newUpdated); /* Preserve indisclustered in the new index */ - newIndexForm->indisclustered = oldIndexForm->indisclustered; + HeapTupleUpdateField(pg_index, indisclustered, oldIndexForm->indisclustered, newIndexForm, newUpdated); /* * Mark the new index as valid, and the old index as invalid similarly to * what index_set_state_flags() does. */ - newIndexForm->indisvalid = true; - oldIndexForm->indisvalid = false; - oldIndexForm->indisclustered = false; - oldIndexForm->indisreplident = false; + HeapTupleUpdateField(pg_index, indisvalid, true, newIndexForm, newUpdated); + HeapTupleUpdateField(pg_index, indisvalid, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indisclustered, false, oldIndexForm, oldUpdated); + HeapTupleUpdateField(pg_index, indisreplident, false, oldIndexForm, oldUpdated); - CatalogTupleUpdate(pg_index, &oldIndexTuple->t_self, oldIndexTuple); - CatalogTupleUpdate(pg_index, &newIndexTuple->t_self, newIndexTuple); + CatalogTupleUpdate(pg_index, &oldIndexTuple->t_self, oldIndexTuple, oldUpdated, NULL); + CatalogTupleUpdate(pg_index, &newIndexTuple->t_self, newIndexTuple, newUpdated, NULL); heap_freetuple(oldIndexTuple); heap_freetuple(newIndexTuple); + bms_free(oldUpdated); + oldUpdated = NULL; + bms_free(newUpdated); + newUpdated = NULL; + /* * Move constraints and triggers over to the new index */ @@ -1686,9 +1700,11 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) if (conForm->conindid == oldIndexId) { - conForm->conindid = newIndexId; + Bitmapset *updated = NULL; - CatalogTupleUpdate(pg_constraint, &constraintTuple->t_self, constraintTuple); + HeapTupleUpdateField(pg_constraint, conindid, newIndexId, conForm, updated); + CatalogTupleUpdate(pg_constraint, &constraintTuple->t_self, constraintTuple, updated, NULL); + bms_free(updated); } heap_freetuple(constraintTuple); @@ -1704,6 +1720,8 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) while (HeapTupleIsValid((triggerTuple = systable_getnext(scan)))) { + Bitmapset *updated = NULL; + Form_pg_trigger tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple); if (tgForm->tgconstrindid != oldIndexId) @@ -1713,10 +1731,9 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) triggerTuple = heap_copytuple(triggerTuple); tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple); - tgForm->tgconstrindid = newIndexId; - - CatalogTupleUpdate(pg_trigger, &triggerTuple->t_self, triggerTuple); - + HeapTupleUpdateField(pg_trigger, tgconstrindid, newIndexId, tgForm, updated); + CatalogTupleUpdate(pg_trigger, &triggerTuple->t_self, triggerTuple, updated, NULL); + bms_free(updated); heap_freetuple(triggerTuple); } @@ -1732,11 +1749,10 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) SysScanDesc sd; HeapTuple tuple; Datum values[Natts_pg_description] = {0}; - bool nulls[Natts_pg_description] = {0}; - bool replaces[Natts_pg_description] = {0}; + bool nulls[Natts_pg_description] = {false}; + Bitmapset *updated = NULL; - values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(newIndexId); - replaces[Anum_pg_description_objoid - 1] = true; + HeapTupleUpdateValue(pg_description, objoid, ObjectIdGetDatum(newIndexId), values, nulls, updated); ScanKeyInit(&skey[0], Anum_pg_description_objoid, @@ -1758,15 +1774,16 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) while ((tuple = systable_getnext(sd)) != NULL) { - tuple = heap_modify_tuple(tuple, RelationGetDescr(description), - values, nulls, replaces); - CatalogTupleUpdate(description, &tuple->t_self, tuple); + tuple = heap_update_tuple(tuple, RelationGetDescr(description), + values, nulls, updated); + CatalogTupleUpdate(description, &tuple->t_self, tuple, updated, NULL); break; /* Assume there can be only one match */ } systable_endscan(sd); table_close(description, NoLock); + bms_free(updated); } /* @@ -2061,6 +2078,7 @@ index_constraint_create(Relation heapRelation, Form_pg_index indexForm; bool dirty = false; bool marked_as_primary = false; + Bitmapset *updated = NULL; pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -2072,20 +2090,20 @@ index_constraint_create(Relation heapRelation, if (mark_as_primary && !indexForm->indisprimary) { - indexForm->indisprimary = true; + HeapTupleUpdateField(pg_index, indisprimary, true, indexForm, updated); dirty = true; marked_as_primary = true; } if (deferrable && indexForm->indimmediate) { - indexForm->indimmediate = false; + HeapTupleUpdateField(pg_index, indimmediate, false, indexForm, updated); dirty = true; } if (dirty) { - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); /* * When we mark an existing index as primary, force a relcache @@ -2102,6 +2120,7 @@ index_constraint_create(Relation heapRelation, heap_freetuple(indexTuple); table_close(pg_index, RowExclusiveLock); + bms_free(updated); } return myself; @@ -3130,6 +3149,7 @@ index_build(Relation heapRelation, Relation pg_index; HeapTuple indexTuple; Form_pg_index indexForm; + Bitmapset *updated = NULL; pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -3142,11 +3162,12 @@ index_build(Relation heapRelation, /* If it's a new index, indcheckxmin shouldn't be set ... */ Assert(!indexForm->indcheckxmin); - indexForm->indcheckxmin = true; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indcheckxmin, true, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); heap_freetuple(indexTuple); table_close(pg_index, RowExclusiveLock); + bms_free(updated); } /* @@ -3505,6 +3526,7 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) Relation pg_index; HeapTuple indexTuple; Form_pg_index indexForm; + Bitmapset *updated = NULL; /* Open pg_index and fetch a writable copy of the index's tuple */ pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -3523,14 +3545,14 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) Assert(indexForm->indislive); Assert(!indexForm->indisready); Assert(!indexForm->indisvalid); - indexForm->indisready = true; + HeapTupleUpdateField(pg_index, indisready, true, indexForm, updated); break; case INDEX_CREATE_SET_VALID: /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */ Assert(indexForm->indislive); Assert(indexForm->indisready); Assert(!indexForm->indisvalid); - indexForm->indisvalid = true; + HeapTupleUpdateField(pg_index, indisvalid, true, indexForm, updated); break; case INDEX_DROP_CLEAR_VALID: @@ -3547,9 +3569,9 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) * set on any invalid index, so clear that flag too. For * cleanliness, also clear indisreplident. */ - indexForm->indisvalid = false; - indexForm->indisclustered = false; - indexForm->indisreplident = false; + HeapTupleUpdateField(pg_index, indisvalid, false, indexForm, updated); + HeapTupleUpdateField(pg_index, indisclustered, false, indexForm, updated); + HeapTupleUpdateField(pg_index, indisreplident, false, indexForm, updated); break; case INDEX_DROP_SET_DEAD: @@ -3563,15 +3585,16 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action) Assert(!indexForm->indisvalid); Assert(!indexForm->indisclustered); Assert(!indexForm->indisreplident); - indexForm->indisready = false; - indexForm->indislive = false; + HeapTupleUpdateField(pg_index, indisready, false, indexForm, updated); + HeapTupleUpdateField(pg_index, indislive, false, indexForm, updated); break; } /* ... and update it */ - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); table_close(pg_index, RowExclusiveLock); + bms_free(updated); } @@ -3850,6 +3873,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, HeapTuple indexTuple; Form_pg_index indexForm; bool index_bad; + Bitmapset *updated = NULL; pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -3866,13 +3890,13 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain)) { if (!indexInfo->ii_BrokenHotChain) - indexForm->indcheckxmin = false; + HeapTupleUpdateField(pg_index, indcheckxmin, false, indexForm, updated); else if (index_bad) - indexForm->indcheckxmin = true; - indexForm->indisvalid = true; - indexForm->indisready = true; - indexForm->indislive = true; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indcheckxmin, true, indexForm, updated); + HeapTupleUpdateField(pg_index, indisvalid, true, indexForm, updated); + HeapTupleUpdateField(pg_index, indisready, true, indexForm, updated); + HeapTupleUpdateField(pg_index, indislive, true, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); /* * Invalidate the relcache for the table, so that after we commit @@ -3885,6 +3909,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId, } table_close(pg_index, RowExclusiveLock); + bms_free(updated); } /* Log what we did */ diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index 004c5121000fe..f35c1b6cd882a 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -225,58 +225,67 @@ CatalogTupleCheckConstraints(Relation heapRel, HeapTuple tup) * * This is a convenience routine for the common case of inserting a single * tuple in a system catalog; it inserts a new heap tuple, keeping indexes - * current. Avoid using it for multiple tuples, since opening the indexes - * and building the index info structures is moderately expensive. - * (Use CatalogTupleInsertWithInfo in such cases.) + * current. + * + * If 'indstate' is NULL, the function opens and closes the indexes internally. + * This is convenient for single-tuple updates but has overhead from opening the + * indexes and building index info structures. + * + * If 'indstate' is provided (non-NULL), it is used directly without opening or + * closing indexes. This allows callers to amortize index management costs across + * multiple tuple updates. Callers must use CatalogOpenIndexes() before the first + * update and CatalogCloseIndexes() after the last update. + * + * XXX: At some point we might cache the CatalogIndexState data somewhere (perhaps + * in the relcache) so that callers needn't trouble over this. */ void -CatalogTupleInsert(Relation heapRel, HeapTuple tup) +CatalogTupleInsert(Relation heapRel, HeapTuple tup, + CatalogIndexState indstate) { - CatalogIndexState indstate; - - CatalogTupleCheckConstraints(heapRel, tup); - - indstate = CatalogOpenIndexes(heapRel); + bool close_indexes = false; - simple_heap_insert(heapRel, tup); - - CatalogIndexInsert(indstate, tup, TU_All); - CatalogCloseIndexes(indstate); -} + /* Open indexes if not provided by caller */ + if (indstate == NULL) + { + indstate = CatalogOpenIndexes(heapRel); + close_indexes = true; + } -/* - * CatalogTupleInsertWithInfo - as above, but with caller-supplied index info - * - * This should be used when it's important to amortize CatalogOpenIndexes/ - * CatalogCloseIndexes work across multiple insertions. At some point we - * might cache the CatalogIndexState data somewhere (perhaps in the relcache) - * so that callers needn't trouble over this ... but we don't do so today. - */ -void -CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, - CatalogIndexState indstate) -{ CatalogTupleCheckConstraints(heapRel, tup); simple_heap_insert(heapRel, tup); CatalogIndexInsert(indstate, tup, TU_All); + + /* Close indexes only if we opened them ourselves */ + if (close_indexes) + CatalogCloseIndexes(indstate); } /* - * CatalogTuplesMultiInsertWithInfo - as above, but for multiple tuples + * CatalogTuplesMultiInsert - as above, but for multiple tuples * * Insert multiple tuples into the given catalog relation at once, with an * amortized cost of CatalogOpenIndexes. */ void -CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, - int ntuples, CatalogIndexState indstate) +CatalogTuplesMultiInsert(Relation heapRel, TupleTableSlot **slot, + int ntuples, CatalogIndexState indstate) { + bool close_indexes = false; + /* Nothing to do */ if (ntuples <= 0) return; + /* Open indexes if not provided by caller */ + if (indstate == NULL) + { + indstate = CatalogOpenIndexes(heapRel); + close_indexes = true; + } + heap_multi_insert(heapRel, slot, ntuples, GetCurrentCommandId(true), 0, NULL); @@ -296,6 +305,10 @@ CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, if (should_free) heap_freetuple(tuple); } + + /* Close indexes only if we opened them ourselves */ + if (close_indexes) + CatalogCloseIndexes(indstate); } /* @@ -303,47 +316,45 @@ CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, * * Update the tuple identified by "otid", replacing it with the data in "tup". * - * This is a convenience routine for the common case of updating a single - * tuple in a system catalog; it updates one heap tuple, keeping indexes - * current. Avoid using it for multiple tuples, since opening the indexes - * and building the index info structures is moderately expensive. - * (Use CatalogTupleUpdateWithInfo in such cases.) + * This function updates a heap tuple in a system catalog and keeps its indexes + * current. The 'updated' bitmapset specifies which columns were modified, using + * the same encoding as HeapDetermineColumnsInfo(). + * + * If 'indstate' is NULL, the function opens and closes the indexes internally. + * This is convenient for single-tuple updates but has overhead from opening the + * indexes and building index info structures. + * + * If 'indstate' is provided (non-NULL), it is used directly without opening or + * closing indexes. This allows callers to amortize index management costs across + * multiple tuple updates. Callers must use CatalogOpenIndexes() before the first + * update and CatalogCloseIndexes() after the last update. + * + * XXX: At some point we might cache the CatalogIndexState data somewhere (perhaps + * in the relcache) so that callers needn't trouble over this. */ void -CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup) +CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tuple, + const Bitmapset *updated, CatalogIndexState indstate) { - CatalogIndexState indstate; TU_UpdateIndexes updateIndexes = TU_All; + bool close_indexes = false; - CatalogTupleCheckConstraints(heapRel, tup); - - indstate = CatalogOpenIndexes(heapRel); - - simple_heap_update(heapRel, otid, tup, &updateIndexes); - - CatalogIndexInsert(indstate, tup, updateIndexes); - CatalogCloseIndexes(indstate); -} + CatalogTupleCheckConstraints(heapRel, tuple); -/* - * CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info - * - * This should be used when it's important to amortize CatalogOpenIndexes/ - * CatalogCloseIndexes work across multiple updates. At some point we - * might cache the CatalogIndexState data somewhere (perhaps in the relcache) - * so that callers needn't trouble over this ... but we don't do so today. - */ -void -CatalogTupleUpdateWithInfo(Relation heapRel, const ItemPointerData *otid, HeapTuple tup, - CatalogIndexState indstate) -{ - TU_UpdateIndexes updateIndexes = TU_All; + /* Open indexes if not provided by caller */ + if (indstate == NULL) + { + indstate = CatalogOpenIndexes(heapRel); + close_indexes = true; + } - CatalogTupleCheckConstraints(heapRel, tup); + simple_heap_update(heapRel, otid, tuple, &updateIndexes); - simple_heap_update(heapRel, otid, tup, &updateIndexes); + CatalogIndexInsert(indstate, tuple, updateIndexes); - CatalogIndexInsert(indstate, tup, updateIndexes); + /* Close indexes only if we opened them ourselves */ + if (close_indexes) + CatalogCloseIndexes(indstate); } /* @@ -355,11 +366,6 @@ CatalogTupleUpdateWithInfo(Relation heapRel, const ItemPointerData *otid, HeapTu * cleanup will be done later by VACUUM. However, callers of this function * shouldn't have to know that; we'd like a uniform abstraction for all * catalog tuple changes. Hence, provide this currently-trivial wrapper. - * - * The abstraction is a bit leaky in that we don't provide an optimized - * CatalogTupleDeleteWithInfo version, because there is currently nothing to - * optimize. If we ever need that, rather than touching a lot of call sites, - * it might be better to do something about caching CatalogIndexState. */ void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid) diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index 93d72157a46ae..bc252da565caf 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -342,6 +342,7 @@ update_default_partition_oid(Oid parentId, Oid defaultPartId) HeapTuple tuple; Relation pg_partitioned_table; Form_pg_partitioned_table part_table_form; + Bitmapset *updated = NULL; pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock); @@ -353,10 +354,12 @@ update_default_partition_oid(Oid parentId, Oid defaultPartId) part_table_form = (Form_pg_partitioned_table) GETSTRUCT(tuple); part_table_form->partdefid = defaultPartId; - CatalogTupleUpdate(pg_partitioned_table, &tuple->t_self, tuple); + HeapTupleMarkColumnUpdated(pg_partitioned_table, partdefid, updated); + CatalogTupleUpdate(pg_partitioned_table, &tuple->t_self, tuple, updated, NULL); heap_freetuple(tuple); table_close(pg_partitioned_table, RowExclusiveLock); + bms_free(updated); } /* diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index a1cb5719a0c6d..ddfa94b3abaf3 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -79,9 +79,9 @@ AggregateCreate(const char *aggName, Relation aggdesc; HeapTuple tup; HeapTuple oldtup; - bool nulls[Natts_pg_aggregate]; - Datum values[Natts_pg_aggregate]; - bool replaces[Natts_pg_aggregate]; + bool nulls[Natts_pg_aggregate] = {false}; + Datum values[Natts_pg_aggregate] = {0}; + Bitmapset *updated = NULL; Form_pg_proc proc; Oid transfn; Oid finalfn = InvalidOid; /* can be omitted */ @@ -102,7 +102,6 @@ AggregateCreate(const char *aggName, Oid procOid; TupleDesc tupDesc; char *detailmsg; - int i; ObjectAddress myself, referenced; ObjectAddresses *addrs; @@ -584,7 +583,7 @@ AggregateCreate(const char *aggName, /* * permission checks on used types */ - for (i = 0; i < numArgs; i++) + for (int i = 0; i < numArgs; i++) { aclresult = object_aclcheck(TypeRelationId, aggArgTypes[i], GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) @@ -651,40 +650,34 @@ AggregateCreate(const char *aggName, tupDesc = aggdesc->rd_att; /* initialize nulls and values */ - for (i = 0; i < Natts_pg_aggregate; i++) - { - nulls[i] = false; - values[i] = (Datum) 0; - replaces[i] = true; - } - values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid); - values[Anum_pg_aggregate_aggkind - 1] = CharGetDatum(aggKind); - values[Anum_pg_aggregate_aggnumdirectargs - 1] = Int16GetDatum(numDirectArgs); - values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn); - values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn); - values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn); - values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn); - values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn); - values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn); - values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn); - values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn); - values[Anum_pg_aggregate_aggfinalextra - 1] = BoolGetDatum(finalfnExtraArgs); - values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs); - values[Anum_pg_aggregate_aggfinalmodify - 1] = CharGetDatum(finalfnModify); - values[Anum_pg_aggregate_aggmfinalmodify - 1] = CharGetDatum(mfinalfnModify); - values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop); - values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType); - values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace); - values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType); - values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace); + HeapTupleUpdateValue(pg_aggregate, aggfnoid, ObjectIdGetDatum(procOid), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggkind, CharGetDatum(aggKind), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggnumdirectargs, Int16GetDatum(numDirectArgs), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggtransfn, ObjectIdGetDatum(transfn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggfinalfn, ObjectIdGetDatum(finalfn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggcombinefn, ObjectIdGetDatum(combinefn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggserialfn, ObjectIdGetDatum(serialfn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggdeserialfn, ObjectIdGetDatum(deserialfn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggmtransfn, ObjectIdGetDatum(mtransfn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggminvtransfn, ObjectIdGetDatum(minvtransfn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggmfinalfn, ObjectIdGetDatum(mfinalfn), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggfinalextra, BoolGetDatum(finalfnExtraArgs), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggmfinalextra, BoolGetDatum(mfinalfnExtraArgs), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggfinalmodify, CharGetDatum(finalfnModify), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggmfinalmodify, CharGetDatum(mfinalfnModify), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggsortop, ObjectIdGetDatum(sortop), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggtranstype, ObjectIdGetDatum(aggTransType), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggtransspace, Int32GetDatum(aggTransSpace), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggmtranstype, ObjectIdGetDatum(aggmTransType), values, nulls, updated); + HeapTupleUpdateValue(pg_aggregate, aggmtransspace, Int32GetDatum(aggmTransSpace), values, nulls, updated); if (agginitval) - values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval); + HeapTupleUpdateValue(pg_aggregate, agginitval, CStringGetTextDatum(agginitval), values, nulls, updated); else - nulls[Anum_pg_aggregate_agginitval - 1] = true; + HeapTupleUpdateValueNull(pg_aggregate, agginitval, values, nulls, updated); if (aggminitval) - values[Anum_pg_aggregate_aggminitval - 1] = CStringGetTextDatum(aggminitval); + HeapTupleUpdateValue(pg_aggregate, aggminitval, CStringGetTextDatum(aggminitval), values, nulls, updated); else - nulls[Anum_pg_aggregate_aggminitval - 1] = true; + HeapTupleUpdateValueNull(pg_aggregate, aggminitval, values, nulls, updated); if (replace) oldtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(procOid)); @@ -717,20 +710,17 @@ AggregateCreate(const char *aggName, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("cannot change number of direct arguments of an aggregate function"))); - replaces[Anum_pg_aggregate_aggfnoid - 1] = false; - replaces[Anum_pg_aggregate_aggkind - 1] = false; - replaces[Anum_pg_aggregate_aggnumdirectargs - 1] = false; - - tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); - CatalogTupleUpdate(aggdesc, &tup->t_self, tup); + tup = heap_update_tuple(oldtup, tupDesc, values, nulls, updated); + CatalogTupleUpdate(aggdesc, &tup->t_self, tup, updated, NULL); ReleaseSysCache(oldtup); } else { tup = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(aggdesc, tup); + CatalogTupleInsert(aggdesc, tup, NULL); } + bms_free(updated); table_close(aggdesc, RowExclusiveLock); /* diff --git a/src/backend/catalog/pg_attrdef.c b/src/backend/catalog/pg_attrdef.c index 29f5691bee9e0..04edc23024e8d 100644 --- a/src/backend/catalog/pg_attrdef.c +++ b/src/backend/catalog/pg_attrdef.c @@ -39,14 +39,12 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin; Relation adrel; HeapTuple tuple; - Datum values[Natts_pg_attrdef]; - static bool nulls[Natts_pg_attrdef] = {false, false, false, false}; + Datum values[Natts_pg_attrdef] = {0}; + bool nulls[Natts_pg_attrdef] = {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}; + Bitmapset *updated = NULL; char attgenerated; Oid attrdefOid; ObjectAddress colobject, @@ -64,13 +62,13 @@ 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] = ObjectIdGetDatum(RelationGetRelid(rel)); - values[Anum_pg_attrdef_adnum - 1] = Int16GetDatum(attnum); - values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin); + HeapTupleSetValue(pg_attrdef, oid, ObjectIdGetDatum(attrdefOid), values); + HeapTupleSetValue(pg_attrdef, adrelid, ObjectIdGetDatum(RelationGetRelid(rel)), values); + HeapTupleSetValue(pg_attrdef, adnum, Int16GetDatum(attnum), values); + HeapTupleSetValue(pg_attrdef, adbin, CStringGetTextDatum(adbin), values); tuple = heap_form_tuple(adrel->rd_att, values, nulls); - CatalogTupleInsert(adrel, tuple); + CatalogTupleInsert(adrel, tuple, NULL); defobject.classId = AttrDefaultRelationId; defobject.objectId = attrdefOid; @@ -79,7 +77,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, table_close(adrel, RowExclusiveLock); /* now can free some of the stuff allocated above */ - pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_attrdef, adbin, values))); heap_freetuple(tuple); pfree(adbin); @@ -91,22 +89,21 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, atttup = SearchSysCacheCopy2(ATTNUM, ObjectIdGetDatum(RelationGetRelid(rel)), Int16GetDatum(attnum)); + if (!HeapTupleIsValid(atttup)) elog(ERROR, "cache lookup failed for attribute %d of relation %u", attnum, RelationGetRelid(rel)); + attStruct = (Form_pg_attribute) GETSTRUCT(atttup); attgenerated = attStruct->attgenerated; - 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); + Assert(bms_is_empty(updated)); + HeapTupleUpdateField(pg_attribute, atthasdef, BoolGetDatum(true), attStruct, updated); + CatalogTupleUpdate(attrrel, &atttup->t_self, atttup, updated, NULL); table_close(attrrel, RowExclusiveLock); heap_freetuple(atttup); + bms_free(updated); /* * Make a dependency so that the pg_attrdef entry goes away if the column @@ -256,7 +253,7 @@ RemoveAttrDefaultById(Oid attrdefId) ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, NULL, NULL); /* * Our update of the pg_attribute row will force a relcache rebuild, so diff --git a/src/backend/catalog/pg_cast.c b/src/backend/catalog/pg_cast.c index 1773c9c549160..8ed900c239251 100644 --- a/src/backend/catalog/pg_cast.c +++ b/src/backend/catalog/pg_cast.c @@ -53,8 +53,8 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, Relation relation; HeapTuple tuple; Oid castid; - Datum values[Natts_pg_cast]; - bool nulls[Natts_pg_cast] = {0}; + Datum values[Natts_pg_cast] = {0}; + bool nulls[Natts_pg_cast] = {false}; ObjectAddress myself, referenced; ObjectAddresses *addrs; @@ -78,16 +78,16 @@ CastCreate(Oid sourcetypeid, Oid targettypeid, /* ready to go */ castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid); - values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid); - values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid); - values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid); - values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid); - values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext); - values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod); + HeapTupleSetValue(pg_cast, oid, ObjectIdGetDatum(castid), values); + HeapTupleSetValue(pg_cast, castsource, ObjectIdGetDatum(sourcetypeid), values); + HeapTupleSetValue(pg_cast, casttarget, ObjectIdGetDatum(targettypeid), values); + HeapTupleSetValue(pg_cast, castfunc, ObjectIdGetDatum(funcid), values); + HeapTupleSetValue(pg_cast, castcontext, CharGetDatum(castcontext), values); + HeapTupleSetValue(pg_cast, castmethod, CharGetDatum(castmethod), values); tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls); - CatalogTupleInsert(relation, tuple); + CatalogTupleInsert(relation, tuple, NULL); addrs = new_object_addresses(); diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c index 469635b35808d..e440bf577e35f 100644 --- a/src/backend/catalog/pg_collation.c +++ b/src/backend/catalog/pg_collation.c @@ -54,8 +54,8 @@ CollationCreate(const char *collname, Oid collnamespace, Relation rel; TupleDesc tupDesc; HeapTuple tup; - Datum values[Natts_pg_collation]; - bool nulls[Natts_pg_collation]; + Datum values[Natts_pg_collation] = {0}; + bool nulls[Natts_pg_collation] = {false}; NameData name_name; Oid oid; ObjectAddress myself, @@ -175,38 +175,38 @@ CollationCreate(const char *collname, Oid collnamespace, namestrcpy(&name_name, collname); oid = GetNewOidWithIndex(rel, CollationOidIndexId, Anum_pg_collation_oid); - values[Anum_pg_collation_oid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name); - values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace); - values[Anum_pg_collation_collowner - 1] = ObjectIdGetDatum(collowner); - values[Anum_pg_collation_collprovider - 1] = CharGetDatum(collprovider); - values[Anum_pg_collation_collisdeterministic - 1] = BoolGetDatum(collisdeterministic); - values[Anum_pg_collation_collencoding - 1] = Int32GetDatum(collencoding); + HeapTupleSetValue(pg_collation, oid, ObjectIdGetDatum(oid), values); + HeapTupleSetValue(pg_collation, collname, NameGetDatum(&name_name), values); + HeapTupleSetValue(pg_collation, collnamespace, ObjectIdGetDatum(collnamespace), values); + HeapTupleSetValue(pg_collation, collowner, ObjectIdGetDatum(collowner), values); + HeapTupleSetValue(pg_collation, collprovider, CharGetDatum(collprovider), values); + HeapTupleSetValue(pg_collation, collisdeterministic, BoolGetDatum(collisdeterministic), values); + HeapTupleSetValue(pg_collation, collencoding, Int32GetDatum(collencoding), values); if (collcollate) - values[Anum_pg_collation_collcollate - 1] = CStringGetTextDatum(collcollate); + HeapTupleSetValue(pg_collation, collcollate, CStringGetTextDatum(collcollate), values); else - nulls[Anum_pg_collation_collcollate - 1] = true; + HeapTupleSetValueNull(pg_collation, collcollate, values, nulls); if (collctype) - values[Anum_pg_collation_collctype - 1] = CStringGetTextDatum(collctype); + HeapTupleSetValue(pg_collation, collctype, CStringGetTextDatum(collctype), values); else - nulls[Anum_pg_collation_collctype - 1] = true; + HeapTupleSetValueNull(pg_collation, collctype, values, nulls); if (colllocale) - values[Anum_pg_collation_colllocale - 1] = CStringGetTextDatum(colllocale); + HeapTupleSetValue(pg_collation, colllocale, CStringGetTextDatum(colllocale), values); else - nulls[Anum_pg_collation_colllocale - 1] = true; + HeapTupleSetValueNull(pg_collation, colllocale, values, nulls); if (collicurules) - values[Anum_pg_collation_collicurules - 1] = CStringGetTextDatum(collicurules); + HeapTupleSetValue(pg_collation, collicurules, CStringGetTextDatum(collicurules), values); else - nulls[Anum_pg_collation_collicurules - 1] = true; + HeapTupleSetValueNull(pg_collation, collicurules, values, nulls); if (collversion) - values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(collversion); + HeapTupleSetValue(pg_collation, collversion, CStringGetTextDatum(collversion), values); else - nulls[Anum_pg_collation_collversion - 1] = true; + HeapTupleSetValueNull(pg_collation, collversion, values, nulls); tup = heap_form_tuple(tupDesc, values, nulls); /* insert a new tuple */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); Assert(OidIsValid(oid)); /* set up dependencies for the new collation */ diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 9944e4bd2d10e..855bdf4601534 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -85,8 +85,8 @@ CreateConstraintEntry(const char *constraintName, Relation conDesc; Oid conOid; HeapTuple tup; - bool nulls[Natts_pg_constraint]; - Datum values[Natts_pg_constraint]; + Datum values[Natts_pg_constraint] = {0}; + bool nulls[Natts_pg_constraint] = {false}; ArrayType *conkeyArray; ArrayType *confkeyArray; ArrayType *conpfeqopArray; @@ -184,70 +184,70 @@ CreateConstraintEntry(const char *constraintName, conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId, Anum_pg_constraint_oid); - values[Anum_pg_constraint_oid - 1] = ObjectIdGetDatum(conOid); - values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname); - values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace); - 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); - values[Anum_pg_constraint_conindid - 1] = ObjectIdGetDatum(indexRelId); - values[Anum_pg_constraint_conparentid - 1] = ObjectIdGetDatum(parentConstrId); - values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId); - values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType); - values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType); - values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType); - 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); + HeapTupleSetValue(pg_constraint, oid, ObjectIdGetDatum(conOid), values); + HeapTupleSetValue(pg_constraint, conname, NameGetDatum(&cname), values); + HeapTupleSetValue(pg_constraint, connamespace, ObjectIdGetDatum(constraintNamespace), values); + HeapTupleSetValue(pg_constraint, contype, CharGetDatum(constraintType), values); + HeapTupleSetValue(pg_constraint, condeferrable, BoolGetDatum(isDeferrable), values); + HeapTupleSetValue(pg_constraint, condeferred, BoolGetDatum(isDeferred), values); + HeapTupleSetValue(pg_constraint, conenforced, BoolGetDatum(isEnforced), values); + HeapTupleSetValue(pg_constraint, convalidated, BoolGetDatum(isValidated), values); + HeapTupleSetValue(pg_constraint, conrelid, ObjectIdGetDatum(relId), values); + HeapTupleSetValue(pg_constraint, contypid, ObjectIdGetDatum(domainId), values); + HeapTupleSetValue(pg_constraint, conindid, ObjectIdGetDatum(indexRelId), values); + HeapTupleSetValue(pg_constraint, conparentid, ObjectIdGetDatum(parentConstrId), values); + HeapTupleSetValue(pg_constraint, confrelid, ObjectIdGetDatum(foreignRelId), values); + HeapTupleSetValue(pg_constraint, confupdtype, CharGetDatum(foreignUpdateType), values); + HeapTupleSetValue(pg_constraint, confdeltype, CharGetDatum(foreignDeleteType), values); + HeapTupleSetValue(pg_constraint, confmatchtype, CharGetDatum(foreignMatchType), values); + HeapTupleSetValue(pg_constraint, conislocal, BoolGetDatum(conIsLocal), values); + HeapTupleSetValue(pg_constraint, coninhcount, Int16GetDatum(conInhCount), values); + HeapTupleSetValue(pg_constraint, connoinherit, BoolGetDatum(conNoInherit), values); + HeapTupleSetValue(pg_constraint, conperiod, BoolGetDatum(conPeriod), values); if (conkeyArray) - values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray); + HeapTupleSetValue(pg_constraint, conkey, PointerGetDatum(conkeyArray), values); else - nulls[Anum_pg_constraint_conkey - 1] = true; + HeapTupleSetValueNull(pg_constraint, conkey, values, nulls); if (confkeyArray) - values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray); + HeapTupleSetValue(pg_constraint, confkey, PointerGetDatum(confkeyArray), values); else - nulls[Anum_pg_constraint_confkey - 1] = true; + HeapTupleSetValueNull(pg_constraint, confkey, values, nulls); if (conpfeqopArray) - values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray); + HeapTupleSetValue(pg_constraint, conpfeqop, PointerGetDatum(conpfeqopArray), values); else - nulls[Anum_pg_constraint_conpfeqop - 1] = true; + HeapTupleSetValueNull(pg_constraint, conpfeqop, values, nulls); if (conppeqopArray) - values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray); + HeapTupleSetValue(pg_constraint, conppeqop, PointerGetDatum(conppeqopArray), values); else - nulls[Anum_pg_constraint_conppeqop - 1] = true; + HeapTupleSetValueNull(pg_constraint, conppeqop, values, nulls); if (conffeqopArray) - values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray); + HeapTupleSetValue(pg_constraint, conffeqop, PointerGetDatum(conffeqopArray), values); else - nulls[Anum_pg_constraint_conffeqop - 1] = true; + HeapTupleSetValueNull(pg_constraint, conffeqop, values, nulls); if (confdelsetcolsArray) - values[Anum_pg_constraint_confdelsetcols - 1] = PointerGetDatum(confdelsetcolsArray); + HeapTupleSetValue(pg_constraint, confdelsetcols, PointerGetDatum(confdelsetcolsArray), values); else - nulls[Anum_pg_constraint_confdelsetcols - 1] = true; + HeapTupleSetValueNull(pg_constraint, confdelsetcols, values, nulls); if (conexclopArray) - values[Anum_pg_constraint_conexclop - 1] = PointerGetDatum(conexclopArray); + HeapTupleSetValue(pg_constraint, conexclop, PointerGetDatum(conexclopArray), values); else - nulls[Anum_pg_constraint_conexclop - 1] = true; + HeapTupleSetValueNull(pg_constraint, conexclop, values, nulls); if (conBin) - values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin); + HeapTupleSetValue(pg_constraint, conbin, CStringGetTextDatum(conBin), values); else - nulls[Anum_pg_constraint_conbin - 1] = true; + HeapTupleSetValueNull(pg_constraint, conbin, values, nulls); tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls); - CatalogTupleInsert(conDesc, tup); + CatalogTupleInsert(conDesc, tup, NULL); ObjectAddressSet(conobject, ConstraintRelationId, conOid); @@ -748,7 +748,7 @@ AdjustNotNullInheritance(Oid relid, AttrNumber attnum, { Relation pg_constraint; Form_pg_constraint conform; - bool changed = false; + Bitmapset *updated = NULL; pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock); conform = (Form_pg_constraint) GETSTRUCT(tup); @@ -784,19 +784,21 @@ AdjustNotNullInheritance(Oid relid, AttrNumber attnum, ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); - changed = true; + HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated); } else if (!conform->conislocal) { - conform->conislocal = true; - changed = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, conform, updated); } - if (changed) - CatalogTupleUpdate(pg_constraint, &tup->t_self, tup); + if (!bms_is_empty(updated)) + { + CatalogTupleUpdate(pg_constraint, &tup->t_self, tup, updated, NULL); + } table_close(pg_constraint, RowExclusiveLock); + bms_free(updated); return true; } @@ -928,6 +930,7 @@ RemoveConstraintById(Oid conId) Relation pgrel; HeapTuple relTup; Form_pg_class classForm; + Bitmapset *updated = NULL; pgrel = table_open(RelationRelationId, RowExclusiveLock); relTup = SearchSysCacheCopy1(RELOID, @@ -938,14 +941,14 @@ RemoveConstraintById(Oid conId) classForm = (Form_pg_class) GETSTRUCT(relTup); if (classForm->relchecks > 0) - classForm->relchecks--; + HeapTupleUpdateField(pg_class, relchecks, classForm->relchecks - 1, classForm, updated); else /* should not happen */ elog(WARNING, "relation \"%s\" has relchecks = %d", RelationGetRelationName(rel), classForm->relchecks); - CatalogTupleUpdate(pgrel, &relTup->t_self, relTup); - + CatalogTupleUpdate(pgrel, &relTup->t_self, relTup, updated, NULL); + bms_free(updated); heap_freetuple(relTup); table_close(pgrel, RowExclusiveLock); @@ -990,6 +993,7 @@ RenameConstraintById(Oid conId, const char *newname) Relation conDesc; HeapTuple tuple; Form_pg_constraint con; + Bitmapset *updated = NULL; conDesc = table_open(ConstraintRelationId, RowExclusiveLock); @@ -1020,11 +1024,13 @@ RenameConstraintById(Oid conId, const char *newname) /* OK, do the rename --- tuple is a copy, so OK to scribble on it */ namestrcpy(&(con->conname), newname); + HeapTupleMarkColumnUpdated(pg_constraint, conname, updated); - CatalogTupleUpdate(conDesc, &tuple->t_self, tuple); + CatalogTupleUpdate(conDesc, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0); + bms_free(updated); heap_freetuple(tuple); table_close(conDesc, RowExclusiveLock); } @@ -1072,15 +1078,17 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId, /* Don't update if the object is already part of the namespace */ if (conform->connamespace == oldNspId && oldNspId != newNspId) { + Bitmapset *updated = NULL; + tup = heap_copytuple(tup); conform = (Form_pg_constraint) GETSTRUCT(tup); - conform->connamespace = newNspId; - - CatalogTupleUpdate(conRel, &tup->t_self, tup); + HeapTupleUpdateField(pg_constraint, connamespace, newNspId, conform, updated); + CatalogTupleUpdate(conRel, &tup->t_self, tup, updated, NULL); + bms_free(updated); /* - * Note: currently, the constraint will not have its own + * NOTE: currently, the constraint will not have its own * dependency on the namespace, so we don't need to do * changeDependencyFor(). */ @@ -1116,6 +1124,7 @@ ConstraintSetParentConstraint(Oid childConstrId, newtup; ObjectAddress depender; ObjectAddress referenced; + Bitmapset *updated = NULL; constrRel = table_open(ConstraintRelationId, RowExclusiveLock); tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId)); @@ -1131,16 +1140,17 @@ ConstraintSetParentConstraint(Oid childConstrId, elog(ERROR, "constraint %u already has a parent constraint", childConstrId); - constrForm->conislocal = false; + HeapTupleUpdateField(pg_constraint, conislocal, false, constrForm, updated); 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; + HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated); + HeapTupleUpdateField(pg_constraint, conparentid, parentConstrId, constrForm, updated); - CatalogTupleUpdate(constrRel, &tuple->t_self, newtup); + CatalogTupleUpdate(constrRel, &tuple->t_self, newtup, updated, NULL); ObjectAddressSet(depender, ConstraintRelationId, childConstrId); @@ -1152,14 +1162,14 @@ ConstraintSetParentConstraint(Oid childConstrId, } else { - constrForm->coninhcount--; - constrForm->conislocal = true; - constrForm->conparentid = InvalidOid; + HeapTupleUpdateField(pg_constraint, coninhcount, constrForm->coninhcount - 1, constrForm, updated); + HeapTupleUpdateField(pg_constraint, conislocal, true, constrForm, updated); + HeapTupleUpdateField(pg_constraint, conparentid, InvalidOid, constrForm, updated); /* Make sure there's no further inheritance. */ Assert(constrForm->coninhcount == 0); - CatalogTupleUpdate(constrRel, &tuple->t_self, newtup); + CatalogTupleUpdate(constrRel, &tuple->t_self, newtup, updated, NULL); deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId, ConstraintRelationId, @@ -1169,6 +1179,7 @@ ConstraintSetParentConstraint(Oid childConstrId, DEPENDENCY_PARTITION_SEC); } + bms_free(updated); ReleaseSysCache(tuple); table_close(constrRel, RowExclusiveLock); } diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 090f680d1908f..247486ba7dec9 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -45,8 +45,8 @@ ConversionCreate(const char *conname, Oid connamespace, TupleDesc tupDesc; HeapTuple tup; Oid oid; - bool nulls[Natts_pg_conversion]; - Datum values[Natts_pg_conversion]; + Datum values[Natts_pg_conversion] = {0}; + bool nulls[Natts_pg_conversion] = {false}; NameData cname; ObjectAddress myself, referenced; @@ -94,19 +94,19 @@ ConversionCreate(const char *conname, Oid connamespace, namestrcpy(&cname, conname); oid = GetNewOidWithIndex(rel, ConversionOidIndexId, Anum_pg_conversion_oid); - values[Anum_pg_conversion_oid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname); - values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace); - values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner); - values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding); - values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding); - values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc); - values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def); + HeapTupleSetValue(pg_conversion, oid, ObjectIdGetDatum(oid), values); + HeapTupleSetValue(pg_conversion, conname, NameGetDatum(&cname), values); + HeapTupleSetValue(pg_conversion, connamespace, ObjectIdGetDatum(connamespace), values); + HeapTupleSetValue(pg_conversion, conowner, ObjectIdGetDatum(conowner), values); + HeapTupleSetValue(pg_conversion, conforencoding, Int32GetDatum(conforencoding), values); + HeapTupleSetValue(pg_conversion, contoencoding, Int32GetDatum(contoencoding), values); + HeapTupleSetValue(pg_conversion, conproc, ObjectIdGetDatum(conproc), values); + HeapTupleSetValue(pg_conversion, condefault, BoolGetDatum(def), values); tup = heap_form_tuple(tupDesc, values, nulls); /* insert a new tuple */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); myself.classId = ConversionRelationId; myself.objectId = oid; diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c index 832e49a34bea5..2e95e28c0c2ac 100644 --- a/src/backend/catalog/pg_db_role_setting.c +++ b/src/backend/catalog/pg_db_role_setting.c @@ -74,21 +74,18 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) if (new) { - Datum repl_val[Natts_pg_db_role_setting]; - bool repl_null[Natts_pg_db_role_setting]; - bool repl_repl[Natts_pg_db_role_setting]; + Datum values[Natts_pg_db_role_setting] = {0}; + bool nulls[Natts_pg_db_role_setting] = {false}; HeapTuple newtuple; + Bitmapset *updated = NULL; - memset(repl_repl, false, sizeof(repl_repl)); + HeapTupleUpdateValue(pg_db_role_setting, setconfig, PointerGetDatum(new), values, nulls, updated); - repl_val[Anum_pg_db_role_setting_setconfig - 1] = - PointerGetDatum(new); - repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true; - repl_null[Anum_pg_db_role_setting_setconfig - 1] = false; + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), + values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + bms_free(updated); } else CatalogTupleDelete(rel, &tuple->t_self); @@ -96,18 +93,14 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) } else if (HeapTupleIsValid(tuple)) { - Datum repl_val[Natts_pg_db_role_setting]; - bool repl_null[Natts_pg_db_role_setting]; - bool repl_repl[Natts_pg_db_role_setting]; + Datum values[Natts_pg_db_role_setting] = {0}; + bool nulls[Natts_pg_db_role_setting] = {false}; + Bitmapset *updated = NULL; HeapTuple newtuple; Datum datum; bool isnull; ArrayType *a; - memset(repl_repl, false, sizeof(repl_repl)); - repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true; - repl_null[Anum_pg_db_role_setting_setconfig - 1] = false; - /* Extract old value of setconfig */ datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig, RelationGetDescr(rel), &isnull); @@ -121,12 +114,12 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) if (a) { - repl_val[Anum_pg_db_role_setting_setconfig - 1] = - PointerGetDatum(a); + HeapTupleUpdateValue(pg_db_role_setting, setconfig, PointerGetDatum(a), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), + values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); + bms_free(updated); } else CatalogTupleDelete(rel, &tuple->t_self); @@ -135,21 +128,18 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt) { /* non-null valuestr means it's not RESET, so insert a new tuple */ HeapTuple newtuple; - Datum values[Natts_pg_db_role_setting]; - bool nulls[Natts_pg_db_role_setting]; + Datum values[Natts_pg_db_role_setting] = {0}; + bool nulls[Natts_pg_db_role_setting] = {false}; ArrayType *a; - memset(nulls, false, sizeof(nulls)); - a = GUCArrayAdd(NULL, setstmt->name, valuestr); - values[Anum_pg_db_role_setting_setdatabase - 1] = - ObjectIdGetDatum(databaseid); - values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid); - values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a); + HeapTupleSetValue(pg_db_role_setting, setdatabase, ObjectIdGetDatum(databaseid), values); + HeapTupleSetValue(pg_db_role_setting, setrole, ObjectIdGetDatum(roleid), values); + HeapTupleSetValue(pg_db_role_setting, setconfig, PointerGetDatum(a), values); newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, newtuple); + CatalogTupleInsert(rel, newtuple, NULL); } else { diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index c8b11f887e274..88deac7f3bd36 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -61,7 +61,7 @@ recordMultipleDependencies(const ObjectAddress *depender, { Relation dependDesc; CatalogIndexState indstate; - TupleTableSlot **slot; + TupleTableSlot **slots; int i, max_slots, slot_init_count, @@ -88,7 +88,7 @@ recordMultipleDependencies(const ObjectAddress *depender, */ max_slots = Min(nreferenced, MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_depend)); - slot = palloc(sizeof(TupleTableSlot *) * max_slots); + slots = palloc(sizeof(TupleTableSlot *) * max_slots); /* Don't open indexes unless we need to make an update */ indstate = NULL; @@ -99,6 +99,9 @@ recordMultipleDependencies(const ObjectAddress *depender, slot_init_count = 0; for (i = 0; i < nreferenced; i++, referenced++) { + TupleTableSlot *slot; + Datum *values; + /* * If the referenced object is pinned by the system, there's no real * need to record dependencies on it. This saves lots of space in @@ -109,29 +112,32 @@ recordMultipleDependencies(const ObjectAddress *depender, if (slot_init_count < max_slots) { - slot[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc), - &TTSOpsHeapTuple); + slots[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc), + &TTSOpsHeapTuple); slot_init_count++; } - ExecClearTuple(slot[slot_stored_count]); + ExecClearTuple(slots[slot_stored_count]); + + slot = slots[slot_stored_count]; + values = slot->tts_values; /* * Record the dependency. Note we don't bother to check for duplicate * dependencies; there's no harm in them. */ - slot[slot_stored_count]->tts_values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior); - slot[slot_stored_count]->tts_values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId); - slot[slot_stored_count]->tts_values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId); - - memset(slot[slot_stored_count]->tts_isnull, false, - slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool)); - - ExecStoreVirtualTuple(slot[slot_stored_count]); + HeapTupleSetValue(pg_depend, refclassid, ObjectIdGetDatum(referenced->classId), values); + HeapTupleSetValue(pg_depend, refobjid, ObjectIdGetDatum(referenced->objectId), values); + HeapTupleSetValue(pg_depend, refobjsubid, Int32GetDatum(referenced->objectSubId), values); + HeapTupleSetValue(pg_depend, deptype, CharGetDatum((char) behavior), values); + HeapTupleSetValue(pg_depend, classid, ObjectIdGetDatum(depender->classId), values); + HeapTupleSetValue(pg_depend, objid, ObjectIdGetDatum(depender->objectId), values); + HeapTupleSetValue(pg_depend, objsubid, Int32GetDatum(depender->objectSubId), values); + + memset(slot->tts_isnull, false, + slot->tts_tupleDescriptor->natts * sizeof(bool)); + + ExecStoreVirtualTuple(slot); slot_stored_count++; /* If slots are full, insert a batch of tuples */ @@ -141,8 +147,7 @@ recordMultipleDependencies(const ObjectAddress *depender, if (indstate == NULL) indstate = CatalogOpenIndexes(dependDesc); - CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(dependDesc, slots, slot_stored_count, indstate); slot_stored_count = 0; } } @@ -154,8 +159,7 @@ recordMultipleDependencies(const ObjectAddress *depender, if (indstate == NULL) indstate = CatalogOpenIndexes(dependDesc); - CatalogTuplesMultiInsertWithInfo(dependDesc, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(dependDesc, slots, slot_stored_count, indstate); } if (indstate != NULL) @@ -165,8 +169,8 @@ recordMultipleDependencies(const ObjectAddress *depender, /* Drop only the number of slots used */ for (i = 0; i < slot_init_count; i++) - ExecDropSingleTupleTableSlot(slot[i]); - pfree(slot); + ExecDropSingleTupleTableSlot(slots[i]); + pfree(slots); } /* @@ -531,14 +535,16 @@ changeDependencyFor(Oid classId, Oid objectId, CatalogTupleDelete(depRel, &tup->t_self); else { + Bitmapset *updated = NULL; + /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); - depform->refobjid = newRefObjectId; - - CatalogTupleUpdate(depRel, &tup->t_self, tup); + HeapTupleUpdateField(pg_depend, refobjid, newRefObjectId, depform, updated); + CatalogTupleUpdate(depRel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); } @@ -588,15 +594,16 @@ changeDependenciesOf(Oid classId, Oid oldObjectId, while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_depend depform; + Bitmapset *updated = NULL; /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); - depform->objid = newObjectId; - - CatalogTupleUpdate(depRel, &tup->t_self, tup); + HeapTupleUpdateField(pg_depend, objid, newObjectId, depform, updated); + CatalogTupleUpdate(depRel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); count++; @@ -675,15 +682,16 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, else { Form_pg_depend depform; + Bitmapset *updated = NULL; /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); - depform->refobjid = newRefObjectId; - - CatalogTupleUpdate(depRel, &tup->t_self, tup); + HeapTupleUpdateField(pg_depend, refobjid, newRefObjectId, depform, updated); + CatalogTupleUpdate(depRel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); } diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c index da9c2a46cfaa1..be87e9ad05697 100644 --- a/src/backend/catalog/pg_enum.c +++ b/src/backend/catalog/pg_enum.c @@ -194,12 +194,12 @@ EnumValuesCreate(Oid enumTypeOid, List *vals) memset(slot[slotCount]->tts_isnull, false, slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool)); - slot[slotCount]->tts_values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(oids[elemno]); - slot[slotCount]->tts_values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid); - slot[slotCount]->tts_values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(elemno + 1); + HeapTupleSetValue(pg_enum, oid, ObjectIdGetDatum(oids[elemno]), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_enum, enumtypid, ObjectIdGetDatum(enumTypeOid), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_enum, enumsortorder, Float4GetDatum(elemno + 1), slot[slotCount]->tts_values); namestrcpy(enumlabel, lab); - slot[slotCount]->tts_values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(enumlabel); + HeapTupleSetValue(pg_enum, enumlabel, NameGetDatum(enumlabel), slot[slotCount]->tts_values); ExecStoreVirtualTuple(slot[slotCount]); slotCount++; @@ -207,8 +207,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals) /* if slots are full, insert a batch of tuples */ if (slotCount == nslots) { - CatalogTuplesMultiInsertWithInfo(pg_enum, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(pg_enum, slot, slotCount, indstate); slotCount = 0; } @@ -217,10 +216,9 @@ EnumValuesCreate(Oid enumTypeOid, List *vals) /* Insert any tuples left in the buffer */ if (slotCount > 0) - CatalogTuplesMultiInsertWithInfo(pg_enum, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(pg_enum, slot, slotCount, indstate); - /* clean up */ + /* Clean up */ pfree(oids); for (int i = 0; i < nslots; i++) ExecDropSingleTupleTableSlot(slot[i]); @@ -310,8 +308,8 @@ AddEnumLabel(Oid enumTypeOid, { Relation pg_enum; Oid newOid; - Datum values[Natts_pg_enum]; - bool nulls[Natts_pg_enum]; + Datum values[Natts_pg_enum] = {0}; + bool nulls[Natts_pg_enum] = {false}; NameData enumlabel; HeapTuple enum_tup; float4 newelemorder; @@ -577,13 +575,13 @@ AddEnumLabel(Oid enumTypeOid, /* Create the new pg_enum entry */ memset(nulls, false, sizeof(nulls)); - values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(newOid); - values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid); - values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(newelemorder); + HeapTupleSetValue(pg_enum, oid, ObjectIdGetDatum(newOid), values); + HeapTupleSetValue(pg_enum, enumtypid, ObjectIdGetDatum(enumTypeOid), values); + HeapTupleSetValue(pg_enum, enumsortorder, Float4GetDatum(newelemorder), values); namestrcpy(&enumlabel, newVal); - values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel); + HeapTupleSetValue(pg_enum, enumlabel, NameGetDatum(&enumlabel), values); enum_tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls); - CatalogTupleInsert(pg_enum, enum_tup); + CatalogTupleInsert(pg_enum, enum_tup, NULL); heap_freetuple(enum_tup); table_close(pg_enum, RowExclusiveLock); @@ -629,6 +627,7 @@ RenameEnumLabel(Oid enumTypeOid, HeapTuple old_tup; bool found_new; int i; + Bitmapset *updated = NULL; /* check length of new label is ok */ if (strlen(newVal) > (NAMEDATALEN - 1)) @@ -689,9 +688,12 @@ RenameEnumLabel(Oid enumTypeOid, /* Update the pg_enum entry */ namestrcpy(&en->enumlabel, newVal); - CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup); - heap_freetuple(enum_tup); + HeapTupleMarkColumnUpdated(pg_enum, enumlabel, updated); + + CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup, updated, NULL); + bms_free(updated); + heap_freetuple(enum_tup); table_close(pg_enum, RowExclusiveLock); } @@ -792,9 +794,12 @@ RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems) newsortorder = i + 1; if (en->enumsortorder != newsortorder) { - en->enumsortorder = newsortorder; + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_enum, enumsortorder, newsortorder, en, updated); - CatalogTupleUpdate(pg_enum, &newtup->t_self, newtup); + CatalogTupleUpdate(pg_enum, &newtup->t_self, newtup, updated, NULL); + bms_free(updated); } heap_freetuple(newtup); diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 929bb53b620fe..a4e0338b54c83 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -507,8 +507,8 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) void StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber) { - Datum values[Natts_pg_inherits]; - bool nulls[Natts_pg_inherits]; + Datum values[Natts_pg_inherits] = {0}; + bool nulls[Natts_pg_inherits] = {false}; HeapTuple tuple; Relation inhRelation; @@ -517,16 +517,16 @@ StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber) /* * Make the pg_inherits entry */ - values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId); - values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid); - values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(seqNumber); - values[Anum_pg_inherits_inhdetachpending - 1] = BoolGetDatum(false); + HeapTupleSetValue(pg_inherits, inhrelid, ObjectIdGetDatum(relationId), values); + HeapTupleSetValue(pg_inherits, inhparent, ObjectIdGetDatum(parentOid), values); + HeapTupleSetValue(pg_inherits, inhseqno, Int32GetDatum(seqNumber), values); + HeapTupleSetValue(pg_inherits, inhdetachpending, BoolGetDatum(false), values); memset(nulls, 0, sizeof(nulls)); tuple = heap_form_tuple(RelationGetDescr(inhRelation), values, nulls); - CatalogTupleInsert(inhRelation, tuple); + CatalogTupleInsert(inhRelation, tuple, NULL); heap_freetuple(tuple); diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c index 33e8fa96a65a8..e49cea5041602 100644 --- a/src/backend/catalog/pg_largeobject.c +++ b/src/backend/catalog/pg_largeobject.c @@ -39,8 +39,8 @@ LargeObjectCreate(Oid loid) Relation pg_lo_meta; HeapTuple ntup; Oid loid_new; - Datum values[Natts_pg_largeobject_metadata]; - bool nulls[Natts_pg_largeobject_metadata]; + Datum values[Natts_pg_largeobject_metadata] = {0}; + bool nulls[Natts_pg_largeobject_metadata] = {false}; Oid ownerId; Acl *lomacl; @@ -50,9 +50,6 @@ LargeObjectCreate(Oid loid) /* * Insert metadata of the largeobject */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - if (OidIsValid(loid)) loid_new = loid; else @@ -62,20 +59,17 @@ LargeObjectCreate(Oid loid) 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(ownerId); + HeapTupleSetValue(pg_largeobject_metadata, oid, ObjectIdGetDatum(loid_new), values); + HeapTupleSetValue(pg_largeobject_metadata, lomowner, ObjectIdGetDatum(ownerId), values); if (lomacl != NULL) - values[Anum_pg_largeobject_metadata_lomacl - 1] - = PointerGetDatum(lomacl); + HeapTupleSetValue(pg_largeobject_metadata, lomacl, PointerGetDatum(lomacl), values); else - nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true; + HeapTupleSetValueNull(pg_largeobject_metadata, lomacl, values, nulls); - ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta), - values, nulls); + ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta), values, nulls); - CatalogTupleInsert(pg_lo_meta, ntup); + CatalogTupleInsert(pg_lo_meta, ntup, NULL); heap_freetuple(ntup); diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c index 616bcc7852113..fa2a970108ca4 100644 --- a/src/backend/catalog/pg_namespace.c +++ b/src/backend/catalog/pg_namespace.c @@ -45,12 +45,11 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp) Relation nspdesc; HeapTuple tup; Oid nspoid; - bool nulls[Natts_pg_namespace]; - Datum values[Natts_pg_namespace]; + bool nulls[Natts_pg_namespace] = {false}; + Datum values[Natts_pg_namespace] = {0}; NameData nname; TupleDesc tupDesc; ObjectAddress myself; - int i; Acl *nspacl; /* sanity checks */ @@ -72,28 +71,21 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp) nspdesc = table_open(NamespaceRelationId, RowExclusiveLock); tupDesc = nspdesc->rd_att; - /* initialize nulls and values */ - for (i = 0; i < Natts_pg_namespace; i++) - { - nulls[i] = false; - values[i] = (Datum) 0; - } - nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId, Anum_pg_namespace_oid); - values[Anum_pg_namespace_oid - 1] = ObjectIdGetDatum(nspoid); + HeapTupleSetValue(pg_namespace, oid, ObjectIdGetDatum(nspoid), values); namestrcpy(&nname, nspName); - values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname); - values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId); + HeapTupleSetValue(pg_namespace, nspname, NameGetDatum(&nname), values); + HeapTupleSetValue(pg_namespace, nspowner, ObjectIdGetDatum(ownerId), values); if (nspacl != NULL) - values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl); + HeapTupleSetValue(pg_namespace, nspacl, PointerGetDatum(nspacl), values); else - nulls[Anum_pg_namespace_nspacl - 1] = true; + HeapTupleSetValueNull(pg_namespace, nspacl, values, nulls); tup = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(nspdesc, tup); + CatalogTupleInsert(nspdesc, tup, NULL); Assert(OidIsValid(nspoid)); table_close(nspdesc, RowExclusiveLock); diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 44d2ccb6788e9..2595ef1d787cd 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -17,6 +17,7 @@ */ #include "postgres.h" +#include "access/htup.h" #include "access/htup_details.h" #include "access/table.h" #include "access/xact.h" @@ -199,10 +200,11 @@ OperatorShellMake(const char *operatorName, Oid operatorObjectId; int i; HeapTuple tup; - Datum values[Natts_pg_operator]; - bool nulls[Natts_pg_operator]; + Datum values[Natts_pg_operator] = {0}; + bool nulls[Natts_pg_operator] = {false}; NameData oname; TupleDesc tupDesc; + Bitmapset *updated = NULL; /* * validate operator name @@ -234,22 +236,23 @@ OperatorShellMake(const char *operatorName, */ operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId, Anum_pg_operator_oid); - values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId); + + HeapTupleUpdateValue(pg_operator, oid, ObjectIdGetDatum(operatorObjectId), values, nulls, updated); namestrcpy(&oname, operatorName); - values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname); - values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace); - values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? 'b' : 'l'); - values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(false); - values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(false); - values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId); - values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId); - values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid); + HeapTupleUpdateValue(pg_operator, oprname, NameGetDatum(&oname), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnamespace, ObjectIdGetDatum(operatorNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprowner, ObjectIdGetDatum(GetUserId()), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprkind, CharGetDatum(leftTypeId ? 'b' : 'l'), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanmerge, BoolGetDatum(false), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanhash, BoolGetDatum(false), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprleft, ObjectIdGetDatum(leftTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprright, ObjectIdGetDatum(rightTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprresult, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcom, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnegate, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcode, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprrest, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprjoin, ObjectIdGetDatum(InvalidOid), values, nulls, updated); /* * create a new operator tuple @@ -259,7 +262,7 @@ OperatorShellMake(const char *operatorName, /* * insert our "shell" operator tuple */ - CatalogTupleInsert(pg_operator_desc, tup); + CatalogTupleInsert(pg_operator_desc, tup, NULL); /* Add dependencies for the entry */ makeOperatorDependencies(tup, true, false); @@ -333,9 +336,9 @@ OperatorCreate(const char *operatorName, Relation pg_operator_desc; HeapTuple tup; bool isUpdate; - bool nulls[Natts_pg_operator]; - bool replaces[Natts_pg_operator]; - Datum values[Natts_pg_operator]; + Datum values[Natts_pg_operator] = {0}; + bool nulls[Natts_pg_operator] = {false}; + Bitmapset *updated = NULL; Oid operatorObjectId; bool operatorAlreadyDefined; Oid operResultType; @@ -343,7 +346,6 @@ OperatorCreate(const char *operatorName, negatorId; bool selfCommutator = false; NameData oname; - int i; ObjectAddress address; /* @@ -447,32 +449,25 @@ OperatorCreate(const char *operatorName, else negatorId = InvalidOid; - /* - * set up values in the operator tuple - */ - - for (i = 0; i < Natts_pg_operator; ++i) - { - values[i] = (Datum) 0; - replaces[i] = true; - nulls[i] = false; - } + /* Set up values in the operator tuple */ + HeapTupleUpdateSetAllColumnsUpdated(pg_operator, updated); + HeapTupleSetColumnNotUpdated(pg_operator, oid, updated); namestrcpy(&oname, operatorName); - values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname); - values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace); - values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? 'b' : 'l'); - values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge); - values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash); - values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId); - values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId); - values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(operResultType); - values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorId); - values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorId); - values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(procedureId); - values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionId); - values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinId); + HeapTupleUpdateValue(pg_operator, oprname, NameGetDatum(&oname), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnamespace, ObjectIdGetDatum(operatorNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprowner, ObjectIdGetDatum(GetUserId()), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprkind, CharGetDatum(leftTypeId ? 'b' : 'l'), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanmerge, BoolGetDatum(canMerge), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcanhash, BoolGetDatum(canHash), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprleft, ObjectIdGetDatum(leftTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprright, ObjectIdGetDatum(rightTypeId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprresult, ObjectIdGetDatum(operResultType), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcom, ObjectIdGetDatum(commutatorId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprnegate, ObjectIdGetDatum(negatorId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprcode, ObjectIdGetDatum(procedureId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprrest, ObjectIdGetDatum(restrictionId), values, nulls, updated); + HeapTupleUpdateValue(pg_operator, oprjoin, ObjectIdGetDatum(joinId), values, nulls, updated); pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock); @@ -489,14 +484,9 @@ OperatorCreate(const char *operatorName, elog(ERROR, "cache lookup failed for operator %u", operatorObjectId); - replaces[Anum_pg_operator_oid - 1] = false; - tup = heap_modify_tuple(tup, - RelationGetDescr(pg_operator_desc), - values, - nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(pg_operator_desc), values, nulls, updated); - CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup, updated, NULL); } else { @@ -505,12 +495,12 @@ OperatorCreate(const char *operatorName, operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId, Anum_pg_operator_oid); - values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId); + HeapTupleUpdateValue(pg_operator, oid, ObjectIdGetDatum(operatorObjectId), values, nulls, updated); tup = heap_form_tuple(RelationGetDescr(pg_operator_desc), values, nulls); - CatalogTupleInsert(pg_operator_desc, tup); + CatalogTupleInsert(pg_operator_desc, tup, NULL); } /* Add dependencies for the entry */ @@ -536,6 +526,7 @@ OperatorCreate(const char *operatorName, /* Post creation hook for new operator */ InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0); + bms_free(updated); table_close(pg_operator_desc, RowExclusiveLock); return address; @@ -708,6 +699,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) if (HeapTupleIsValid(tup)) { Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup); + Bitmapset *updated = NULL; bool update_commutator = false; /* @@ -717,7 +709,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) */ if (isDelete && OidIsValid(t->oprcom)) { - t->oprcom = InvalidOid; + HeapTupleUpdateField(pg_operator, oprcom, InvalidOid, t, updated); update_commutator = true; } else if (!isDelete && t->oprcom != baseId) @@ -745,14 +737,14 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) NameStr(t->oprname), t->oprcom))); } - t->oprcom = baseId; + HeapTupleUpdateField(pg_operator, oprcom, baseId, t, updated); update_commutator = true; } /* If any columns were found to need modification, update tuple. */ if (update_commutator) { - CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup, updated, NULL); /* * Do CCI to make the updated tuple visible. We must do this in @@ -763,6 +755,8 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) */ CommandCounterIncrement(); } + + bms_free(updated); } /* @@ -777,6 +771,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) { Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup); bool update_negator = false; + Bitmapset *updated = NULL; /* * We can skip doing anything if the negator's oprnegate field is @@ -785,7 +780,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) */ if (isDelete && OidIsValid(t->oprnegate)) { - t->oprnegate = InvalidOid; + HeapTupleUpdateField(pg_operator, oprnegate, InvalidOid, t, updated); update_negator = true; } else if (!isDelete && t->oprnegate != baseId) @@ -813,14 +808,14 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) NameStr(t->oprname), t->oprnegate))); } - t->oprnegate = baseId; + HeapTupleUpdateField(pg_operator, oprnegate, baseId, t, updated); update_negator = true; } /* If any columns were found to need modification, update tuple. */ if (update_negator) { - CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup, updated, NULL); /* * In the deletion case, do CCI to make the updated tuple visible. @@ -831,6 +826,8 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete) if (isDelete) CommandCounterIncrement(); } + + bms_free(updated); } /* Close relation and release catalog lock. */ diff --git a/src/backend/catalog/pg_parameter_acl.c b/src/backend/catalog/pg_parameter_acl.c index dcdf49ea408d6..04e3545552db9 100644 --- a/src/backend/catalog/pg_parameter_acl.c +++ b/src/backend/catalog/pg_parameter_acl.c @@ -74,7 +74,7 @@ ParameterAclCreate(const char *parameter) TupleDesc tupDesc; HeapTuple tuple; Datum values[Natts_pg_parameter_acl] = {0}; - bool nulls[Natts_pg_parameter_acl] = {0}; + bool nulls[Natts_pg_parameter_acl] = {false}; /* * To prevent cluttering pg_parameter_acl with useless entries, insist @@ -96,12 +96,11 @@ ParameterAclCreate(const char *parameter) parameterId = GetNewOidWithIndex(rel, ParameterAclOidIndexId, Anum_pg_parameter_acl_oid); - values[Anum_pg_parameter_acl_oid - 1] = ObjectIdGetDatum(parameterId); - values[Anum_pg_parameter_acl_parname - 1] = - PointerGetDatum(cstring_to_text(parname)); - nulls[Anum_pg_parameter_acl_paracl - 1] = true; + HeapTupleSetValue(pg_parameter_acl, oid, ObjectIdGetDatum(parameterId), values); + HeapTupleSetValue(pg_parameter_acl, parname, PointerGetDatum(cstring_to_text(parname)), values); + HeapTupleSetValueNull(pg_parameter_acl, paracl, values, nulls); tuple = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); /* Close pg_parameter_acl, but keep lock till commit. */ heap_freetuple(tuple); diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index b89b9ccda0ed9..252a2f4aedac2 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -14,6 +14,7 @@ */ #include "postgres.h" +#include "access/htup.h" #include "access/htup_details.h" #include "access/table.h" #include "access/xact.h" @@ -134,9 +135,9 @@ ProcedureCreate(const char *procedureName, Relation rel; HeapTuple tup; HeapTuple oldtup; - bool nulls[Natts_pg_proc]; - Datum values[Natts_pg_proc]; - bool replaces[Natts_pg_proc]; + Datum values[Natts_pg_proc] = {0}; + bool nulls[Natts_pg_proc] = {false}; + Bitmapset *updated = NULL; NameData procname; TupleDesc tupDesc; bool is_update; @@ -316,67 +317,61 @@ ProcedureCreate(const char *procedureName, /* * All seems OK; prepare the data to be inserted into pg_proc. */ - - for (i = 0; i < Natts_pg_proc; ++i) - { - nulls[i] = false; - values[i] = (Datum) 0; - replaces[i] = true; - } + HeapTupleUpdateSetAllColumnsUpdated(pg_proc, updated); namestrcpy(&procname, procedureName); - values[Anum_pg_proc_proname - 1] = NameGetDatum(&procname); - values[Anum_pg_proc_pronamespace - 1] = ObjectIdGetDatum(procNamespace); - values[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(proowner); - values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId); - values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost); - values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows); - values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType); - values[Anum_pg_proc_prosupport - 1] = ObjectIdGetDatum(prosupport); - values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind); - values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer); - values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof); - values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict); - values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet); - values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility); - values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel); - values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount); - values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults)); - values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType); - values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes); + HeapTupleUpdateValue(pg_proc, proname, NameGetDatum(&procname), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, pronamespace, ObjectIdGetDatum(procNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proowner, ObjectIdGetDatum(proowner), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prolang, ObjectIdGetDatum(languageObjectId), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, procost, Float4GetDatum(procost), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prorows, Float4GetDatum(prorows), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, provariadic, ObjectIdGetDatum(variadicType), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prosupport, ObjectIdGetDatum(prosupport), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prokind, CharGetDatum(prokind), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prosecdef, BoolGetDatum(security_definer), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proleakproof, BoolGetDatum(isLeakProof), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proisstrict, BoolGetDatum(isStrict), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proretset, BoolGetDatum(returnsSet), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, provolatile, CharGetDatum(volatility), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proparallel, CharGetDatum(parallel), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, pronargs, UInt16GetDatum(parameterCount), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, pronargdefaults, UInt16GetDatum(list_length(parameterDefaults)), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prorettype, ObjectIdGetDatum(returnType), values, nulls, updated); + HeapTupleUpdateValue(pg_proc, proargtypes, PointerGetDatum(parameterTypes), values, nulls, updated); if (allParameterTypes != PointerGetDatum(NULL)) - values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes; + HeapTupleUpdateValue(pg_proc, proallargtypes, allParameterTypes, values, nulls, updated); else - nulls[Anum_pg_proc_proallargtypes - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proallargtypes, values, nulls, updated); if (parameterModes != PointerGetDatum(NULL)) - values[Anum_pg_proc_proargmodes - 1] = parameterModes; + HeapTupleUpdateValue(pg_proc, proargmodes, parameterModes, values, nulls, updated); else - nulls[Anum_pg_proc_proargmodes - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proargmodes, values, nulls, updated); if (parameterNames != PointerGetDatum(NULL)) - values[Anum_pg_proc_proargnames - 1] = parameterNames; + HeapTupleUpdateValue(pg_proc, proargnames, parameterNames, values, nulls, updated); else - nulls[Anum_pg_proc_proargnames - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proargnames, values, nulls, updated); if (parameterDefaults != NIL) - values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults)); + HeapTupleUpdateValue(pg_proc, proargdefaults, CStringGetTextDatum(nodeToString(parameterDefaults)), values, nulls, updated); else - nulls[Anum_pg_proc_proargdefaults - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proargdefaults, values, nulls, updated); if (trftypes != PointerGetDatum(NULL)) - values[Anum_pg_proc_protrftypes - 1] = trftypes; + HeapTupleUpdateValue(pg_proc, protrftypes, trftypes, values, nulls, updated); else - nulls[Anum_pg_proc_protrftypes - 1] = true; - values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc); + HeapTupleUpdateValueNull(pg_proc, protrftypes, values, nulls, updated); + HeapTupleUpdateValue(pg_proc, prosrc, CStringGetTextDatum(prosrc), values, nulls, updated); if (probin) - values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin); + HeapTupleUpdateValue(pg_proc, probin, CStringGetTextDatum(probin), values, nulls, updated); else - nulls[Anum_pg_proc_probin - 1] = true; + HeapTupleUpdateValueNull(pg_proc, probin, values, nulls, updated); if (prosqlbody) - values[Anum_pg_proc_prosqlbody - 1] = CStringGetTextDatum(nodeToString(prosqlbody)); + HeapTupleUpdateValue(pg_proc, prosqlbody, CStringGetTextDatum(nodeToString(prosqlbody)), values, nulls, updated); else - nulls[Anum_pg_proc_prosqlbody - 1] = true; + HeapTupleUpdateValueNull(pg_proc, prosqlbody, values, nulls, updated); if (proconfig != PointerGetDatum(NULL)) - values[Anum_pg_proc_proconfig - 1] = proconfig; + HeapTupleUpdateValue(pg_proc, proconfig, proconfig, values, nulls, updated); else - nulls[Anum_pg_proc_proconfig - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proconfig, values, nulls, updated); /* proacl will be determined later */ rel = table_open(ProcedureRelationId, RowExclusiveLock); @@ -577,13 +572,13 @@ ProcedureCreate(const char *procedureName, * Do not change existing oid, ownership or permissions, either. Note * dependency-update code below has to agree with this decision. */ - replaces[Anum_pg_proc_oid - 1] = false; - replaces[Anum_pg_proc_proowner - 1] = false; - replaces[Anum_pg_proc_proacl - 1] = false; + HeapTupleSetColumnNotUpdated(pg_proc, oid, updated); + HeapTupleSetColumnNotUpdated(pg_proc, proowner, updated); + HeapTupleSetColumnNotUpdated(pg_proc, proacl, updated); /* Okay, do it... */ - tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(oldtup, tupDesc, values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); ReleaseSysCache(oldtup); is_update = true; @@ -597,18 +592,23 @@ ProcedureCreate(const char *procedureName, proacl = get_user_default_acl(OBJECT_FUNCTION, proowner, procNamespace); if (proacl != NULL) - values[Anum_pg_proc_proacl - 1] = PointerGetDatum(proacl); + HeapTupleUpdateValue(pg_proc, proacl, PointerGetDatum(proacl), values, nulls, updated); else - nulls[Anum_pg_proc_proacl - 1] = true; + HeapTupleUpdateValueNull(pg_proc, proacl, values, nulls, updated); newOid = GetNewOidWithIndex(rel, ProcedureOidIndexId, Anum_pg_proc_oid); - values[Anum_pg_proc_oid - 1] = ObjectIdGetDatum(newOid); + HeapTupleUpdateValue(pg_proc, oid, ObjectIdGetDatum(newOid), values, nulls, updated); + + /* Okay, do it... */ tup = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); + is_update = false; } + bms_free(updated); + updated = NULL; retval = ((Form_pg_proc) GETSTRUCT(tup))->oid; diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index ac2f4ee35616c..9521b7cd3a47d 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -433,8 +433,8 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, { Relation rel; HeapTuple tup; - Datum values[Natts_pg_publication_rel]; - bool nulls[Natts_pg_publication_rel]; + Datum values[Natts_pg_publication_rel] = {0}; + bool nulls[Natts_pg_publication_rel] = {false}; Relation targetrel = pri->relation; Oid relid = RelationGetRelid(targetrel); Oid pubreloid; @@ -477,28 +477,26 @@ publication_add_relation(Oid pubid, PublicationRelInfo *pri, pubreloid = GetNewOidWithIndex(rel, PublicationRelObjectIndexId, Anum_pg_publication_rel_oid); - values[Anum_pg_publication_rel_oid - 1] = ObjectIdGetDatum(pubreloid); - values[Anum_pg_publication_rel_prpubid - 1] = - ObjectIdGetDatum(pubid); - values[Anum_pg_publication_rel_prrelid - 1] = - ObjectIdGetDatum(relid); + HeapTupleSetValue(pg_publication_rel, oid, ObjectIdGetDatum(pubreloid), values); + HeapTupleSetValue(pg_publication_rel, prpubid, ObjectIdGetDatum(pubid), values); + HeapTupleSetValue(pg_publication_rel, prrelid, ObjectIdGetDatum(relid), values); /* Add qualifications, if available */ if (pri->whereClause != NULL) - values[Anum_pg_publication_rel_prqual - 1] = CStringGetTextDatum(nodeToString(pri->whereClause)); + HeapTupleSetValue(pg_publication_rel, prqual, CStringGetTextDatum(nodeToString(pri->whereClause)), values); else - nulls[Anum_pg_publication_rel_prqual - 1] = true; + HeapTupleSetValueNull(pg_publication_rel, prqual, values, nulls); /* Add column list, if available */ if (pri->columns) - values[Anum_pg_publication_rel_prattrs - 1] = PointerGetDatum(attnumstoint2vector(attnums)); + HeapTupleSetValue(pg_publication_rel, prattrs, PointerGetDatum(attnumstoint2vector(attnums)), values); else - nulls[Anum_pg_publication_rel_prattrs - 1] = true; + HeapTupleSetValueNull(pg_publication_rel, prattrs, values, nulls); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); /* Register dependencies as needed */ @@ -674,8 +672,8 @@ publication_add_schema(Oid pubid, Oid schemaid, bool if_not_exists) { Relation rel; HeapTuple tup; - Datum values[Natts_pg_publication_namespace]; - bool nulls[Natts_pg_publication_namespace]; + Datum values[Natts_pg_publication_namespace] = {0}; + bool nulls[Natts_pg_publication_namespace] = {false}; Oid psschid; Publication *pub = GetPublication(pubid); List *schemaRels = NIL; @@ -712,16 +710,14 @@ publication_add_schema(Oid pubid, Oid schemaid, bool if_not_exists) psschid = GetNewOidWithIndex(rel, PublicationNamespaceObjectIndexId, Anum_pg_publication_namespace_oid); - values[Anum_pg_publication_namespace_oid - 1] = ObjectIdGetDatum(psschid); - values[Anum_pg_publication_namespace_pnpubid - 1] = - ObjectIdGetDatum(pubid); - values[Anum_pg_publication_namespace_pnnspid - 1] = - ObjectIdGetDatum(schemaid); + HeapTupleSetValue(pg_publication_namespace, oid, ObjectIdGetDatum(psschid), values); + HeapTupleSetValue(pg_publication_namespace, pnpubid, ObjectIdGetDatum(pubid), values); + HeapTupleSetValue(pg_publication_namespace, pnnspid, ObjectIdGetDatum(schemaid), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); ObjectAddressSet(myself, PublicationNamespaceRelationId, psschid); diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c index 8df73e7ab71b4..4e4d2d37d107c 100644 --- a/src/backend/catalog/pg_range.c +++ b/src/backend/catalog/pg_range.c @@ -38,8 +38,8 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation, RegProcedure rangeSubDiff, Oid multirangeTypeOid) { Relation pg_range; - Datum values[Natts_pg_range]; - bool nulls[Natts_pg_range]; + Datum values[Natts_pg_range] = {0}; + bool nulls[Natts_pg_range] = {false}; HeapTuple tup; ObjectAddress myself; ObjectAddress referenced; @@ -50,17 +50,17 @@ RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation, memset(nulls, 0, sizeof(nulls)); - values[Anum_pg_range_rngtypid - 1] = ObjectIdGetDatum(rangeTypeOid); - values[Anum_pg_range_rngsubtype - 1] = ObjectIdGetDatum(rangeSubType); - values[Anum_pg_range_rngcollation - 1] = ObjectIdGetDatum(rangeCollation); - values[Anum_pg_range_rngsubopc - 1] = ObjectIdGetDatum(rangeSubOpclass); - values[Anum_pg_range_rngcanonical - 1] = ObjectIdGetDatum(rangeCanonical); - values[Anum_pg_range_rngsubdiff - 1] = ObjectIdGetDatum(rangeSubDiff); - values[Anum_pg_range_rngmultitypid - 1] = ObjectIdGetDatum(multirangeTypeOid); + HeapTupleSetValue(pg_range, rngtypid, ObjectIdGetDatum(rangeTypeOid), values); + HeapTupleSetValue(pg_range, rngsubtype, ObjectIdGetDatum(rangeSubType), values); + HeapTupleSetValue(pg_range, rngcollation, ObjectIdGetDatum(rangeCollation), values); + HeapTupleSetValue(pg_range, rngsubopc, ObjectIdGetDatum(rangeSubOpclass), values); + HeapTupleSetValue(pg_range, rngcanonical, ObjectIdGetDatum(rangeCanonical), values); + HeapTupleSetValue(pg_range, rngsubdiff, ObjectIdGetDatum(rangeSubDiff), values); + HeapTupleSetValue(pg_range, rngmultitypid, ObjectIdGetDatum(multirangeTypeOid), values); tup = heap_form_tuple(RelationGetDescr(pg_range), values, nulls); - CatalogTupleInsert(pg_range, tup); + CatalogTupleInsert(pg_range, tup, NULL); heap_freetuple(tup); /* record type's dependencies on range-related items */ diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index 16e3e5c7457db..750f0d69e5757 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -273,31 +273,31 @@ shdepChangeDep(Relation sdepRel, shForm->refclassid = refclassid; shForm->refobjid = refobjid; - CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup); + CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup, NULL, NULL); } else { /* Need to insert new entry */ - Datum values[Natts_pg_shdepend]; - bool nulls[Natts_pg_shdepend]; + Datum values[Natts_pg_shdepend] = {0}; + bool nulls[Natts_pg_shdepend] = {false}; memset(nulls, false, sizeof(nulls)); - values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid); - values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid); - values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid); - values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid); + HeapTupleSetValue(pg_shdepend, dbid, ObjectIdGetDatum(dbid), values); + HeapTupleSetValue(pg_shdepend, classid, ObjectIdGetDatum(classid), values); + HeapTupleSetValue(pg_shdepend, objid, ObjectIdGetDatum(objid), values); + HeapTupleSetValue(pg_shdepend, objsubid, Int32GetDatum(objsubid), values); - values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid); - values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid); - values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype); + HeapTupleSetValue(pg_shdepend, refclassid, ObjectIdGetDatum(refclassid), values); + HeapTupleSetValue(pg_shdepend, refobjid, ObjectIdGetDatum(refobjid), values); + HeapTupleSetValue(pg_shdepend, deptype, CharGetDatum(deptype), values); /* * we are reusing oldtup just to avoid declaring a new variable, but * it's certainly a new tuple */ oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls); - CatalogTupleInsert(sdepRel, oldtup); + CatalogTupleInsert(sdepRel, oldtup, NULL); } if (oldtup) @@ -955,13 +955,13 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId) shdep = (Form_pg_shdepend) GETSTRUCT(tup); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(shdep->classid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(shdep->objid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(shdep->objsubid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(shdep->refclassid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(shdep->refobjid); - slot[slot_stored_count]->tts_values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(shdep->deptype); + HeapTupleSetValue(pg_shdepend, dbid, ObjectIdGetDatum(newDbId), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, classid, ObjectIdGetDatum(shdep->classid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, objid, ObjectIdGetDatum(shdep->objid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, objsubid, Int32GetDatum(shdep->objsubid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, refclassid, ObjectIdGetDatum(shdep->refclassid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, refobjid, ObjectIdGetDatum(shdep->refobjid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_shdepend, deptype, CharGetDatum(shdep->deptype), slot[slot_stored_count]->tts_values); ExecStoreVirtualTuple(slot[slot_stored_count]); slot_stored_count++; @@ -969,14 +969,14 @@ copyTemplateDependencies(Oid templateDbId, Oid newDbId) /* If slots are full, insert a batch of tuples */ if (slot_stored_count == max_slots) { - CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate); + CatalogTuplesMultiInsert(sdepRel, slot, slot_stored_count, indstate); slot_stored_count = 0; } } /* Insert any tuples left in the buffer */ if (slot_stored_count > 0) - CatalogTuplesMultiInsertWithInfo(sdepRel, slot, slot_stored_count, indstate); + CatalogTuplesMultiInsert(sdepRel, slot, slot_stored_count, indstate); systable_endscan(scan); @@ -1072,8 +1072,8 @@ shdepAddDependency(Relation sdepRel, SharedDependencyType deptype) { HeapTuple tup; - Datum values[Natts_pg_shdepend]; - bool nulls[Natts_pg_shdepend]; + Datum values[Natts_pg_shdepend] = {0}; + bool nulls[Natts_pg_shdepend] = {false}; /* * Make sure the object doesn't go away while we record the dependency on @@ -1087,18 +1087,18 @@ shdepAddDependency(Relation sdepRel, /* * Form the new tuple and record the dependency. */ - values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId)); - values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId); - values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId); - values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId); + HeapTupleSetValue(pg_shdepend, dbid, ObjectIdGetDatum(classIdGetDbId(classId)), values); + HeapTupleSetValue(pg_shdepend, classid, ObjectIdGetDatum(classId), values); + HeapTupleSetValue(pg_shdepend, objid, ObjectIdGetDatum(objectId), values); + HeapTupleSetValue(pg_shdepend, objsubid, Int32GetDatum(objsubId), values); - values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId); - values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId); - values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype); + HeapTupleSetValue(pg_shdepend, refclassid, ObjectIdGetDatum(refclassId), values); + HeapTupleSetValue(pg_shdepend, refobjid, ObjectIdGetDatum(refobjId), values); + HeapTupleSetValue(pg_shdepend, deptype, CharGetDatum(deptype), values); tup = heap_form_tuple(sdepRel->rd_att, values, nulls); - CatalogTupleInsert(sdepRel, tup); + CatalogTupleInsert(sdepRel, tup, NULL); /* clean up */ heap_freetuple(tup); diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index 180e77e94845b..59765a8cea069 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -203,9 +203,9 @@ void DisableSubscription(Oid subid) { Relation rel; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; + Bitmapset *updated = NULL; HeapTuple tup; /* Look up the subscription in the catalog */ @@ -217,19 +217,13 @@ DisableSubscription(Oid subid) LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock); - /* Form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - /* Set the subscription to disabled. */ - values[Anum_pg_subscription_subenabled - 1] = BoolGetDatum(false); - replaces[Anum_pg_subscription_subenabled - 1] = true; + HeapTupleUpdateValue(pg_subscription, subenabled, BoolGetDatum(false), values, nulls, updated); /* Update the catalog */ - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); heap_freetuple(tup); table_close(rel, NoLock); @@ -272,8 +266,8 @@ AddSubscriptionRelState(Oid subid, Oid relid, char state, { Relation rel; HeapTuple tup; - bool nulls[Natts_pg_subscription_rel]; - Datum values[Natts_pg_subscription_rel]; + Datum values[Natts_pg_subscription_rel] = {0}; + bool nulls[Natts_pg_subscription_rel] = {false}; LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock); @@ -288,20 +282,18 @@ AddSubscriptionRelState(Oid subid, Oid relid, char state, relid, subid); /* Form the tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - values[Anum_pg_subscription_rel_srsubid - 1] = ObjectIdGetDatum(subid); - values[Anum_pg_subscription_rel_srrelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state); + HeapTupleSetValue(pg_subscription_rel, srsubid, ObjectIdGetDatum(subid), values); + HeapTupleSetValue(pg_subscription_rel, srrelid, ObjectIdGetDatum(relid), values); + HeapTupleSetValue(pg_subscription_rel, srsubstate, CharGetDatum(state), values); if (XLogRecPtrIsValid(sublsn)) - values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn); + HeapTupleSetValue(pg_subscription_rel, srsublsn, LSNGetDatum(sublsn), values); else - nulls[Anum_pg_subscription_rel_srsublsn - 1] = true; + HeapTupleSetValueNull(pg_subscription_rel, srsublsn, values, nulls); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -326,9 +318,9 @@ UpdateSubscriptionRelState(Oid subid, Oid relid, char state, { Relation rel; HeapTuple tup; - bool nulls[Natts_pg_subscription_rel]; - Datum values[Natts_pg_subscription_rel]; - bool replaces[Natts_pg_subscription_rel]; + Datum values[Natts_pg_subscription_rel] = {0}; + bool nulls[Natts_pg_subscription_rel] = {false}; + Bitmapset *updated = NULL; if (already_locked) { @@ -358,27 +350,21 @@ UpdateSubscriptionRelState(Oid subid, Oid relid, char state, relid, subid); /* Update the tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - - replaces[Anum_pg_subscription_rel_srsubstate - 1] = true; - values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state); + HeapTupleUpdateValue(pg_subscription_rel, srsubstate, CharGetDatum(state), values, nulls, updated); - replaces[Anum_pg_subscription_rel_srsublsn - 1] = true; if (XLogRecPtrIsValid(sublsn)) - values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn); + HeapTupleUpdateValue(pg_subscription_rel, srsublsn, LSNGetDatum(sublsn), values, nulls, updated); else - nulls[Anum_pg_subscription_rel_srsublsn - 1] = true; + HeapTupleUpdateValueNull(pg_subscription_rel, srsublsn, values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); /* Update the catalog. */ - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Cleanup. */ table_close(rel, NoLock); + bms_free(updated); } /* @@ -645,9 +631,9 @@ void UpdateDeadTupleRetentionStatus(Oid subid, bool active) { Relation rel; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; + Bitmapset *updated = NULL; HeapTuple tup; /* Look up the subscription in the catalog */ @@ -659,20 +645,16 @@ UpdateDeadTupleRetentionStatus(Oid subid, bool active) LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock); - /* Form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - /* Set the subscription to disabled. */ - values[Anum_pg_subscription_subretentionactive - 1] = active; - replaces[Anum_pg_subscription_subretentionactive - 1] = true; + HeapTupleUpdateValue(pg_subscription, subretentionactive, active, values, nulls, updated); /* Update the catalog */ - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); - heap_freetuple(tup); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + + /* Cleanup */ + bms_free(updated); + heap_freetuple(tup); table_close(rel, NoLock); } diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 257c7da856832..6342f9aad07fb 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -60,8 +60,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) TupleDesc tupDesc; int i; HeapTuple tup; - Datum values[Natts_pg_type]; - bool nulls[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; Oid typoid; NameData name; ObjectAddress address; @@ -92,37 +92,37 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) * mistaken for a usable type. */ namestrcpy(&name, typeName); - values[Anum_pg_type_typname - 1] = NameGetDatum(&name); - values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace); - values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId); - values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32)); - values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true); - values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO); - values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE); - values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false); - values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false); - values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM); - values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN); - values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT); - values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT); - values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN); - values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false); - values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1); - values[Anum_pg_type_typndims - 1] = Int32GetDatum(0); - values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid); - nulls[Anum_pg_type_typdefaultbin - 1] = true; - nulls[Anum_pg_type_typdefault - 1] = true; - nulls[Anum_pg_type_typacl - 1] = true; + HeapTupleSetValue(pg_type, typname, NameGetDatum(&name), values); + HeapTupleSetValue(pg_type, typnamespace, ObjectIdGetDatum(typeNamespace), values); + HeapTupleSetValue(pg_type, typowner, ObjectIdGetDatum(ownerId), values); + HeapTupleSetValue(pg_type, typlen, Int16GetDatum(sizeof(int32)), values); + HeapTupleSetValue(pg_type, typbyval, BoolGetDatum(true), values); + HeapTupleSetValue(pg_type, typtype, CharGetDatum(TYPTYPE_PSEUDO), values); + HeapTupleSetValue(pg_type, typcategory, CharGetDatum(TYPCATEGORY_PSEUDOTYPE), values); + HeapTupleSetValue(pg_type, typispreferred, BoolGetDatum(false), values); + HeapTupleSetValue(pg_type, typisdefined, BoolGetDatum(false), values); + HeapTupleSetValue(pg_type, typdelim, CharGetDatum(DEFAULT_TYPDELIM), values); + HeapTupleSetValue(pg_type, typrelid, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typsubscript, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typelem, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typarray, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typinput, ObjectIdGetDatum(F_SHELL_IN), values); + HeapTupleSetValue(pg_type, typoutput, ObjectIdGetDatum(F_SHELL_OUT), values); + HeapTupleSetValue(pg_type, typreceive, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typsend, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typmodin, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typmodout, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typanalyze, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typalign, CharGetDatum(TYPALIGN_INT), values); + HeapTupleSetValue(pg_type, typstorage, CharGetDatum(TYPSTORAGE_PLAIN), values); + HeapTupleSetValue(pg_type, typnotnull, BoolGetDatum(false), values); + HeapTupleSetValue(pg_type, typbasetype, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_type, typtypmod, Int32GetDatum(-1), values); + HeapTupleSetValue(pg_type, typndims, Int32GetDatum(0), values); + HeapTupleSetValue(pg_type, typcollation, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValueNull(pg_type, typdefaultbin, values, nulls); + HeapTupleSetValueNull(pg_type, typdefault, values, nulls); + HeapTupleSetValueNull(pg_type, typacl, values, nulls); /* Use binary-upgrade override for pg_type.oid? */ if (IsBinaryUpgrade) @@ -141,7 +141,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) Anum_pg_type_oid); } - values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid); + HeapTupleSetValue(pg_type, oid, ObjectIdGetDatum(typoid), values); /* * create a new type tuple @@ -151,7 +151,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) /* * insert the tuple in the relation and get the tuple's oid. */ - CatalogTupleInsert(pg_type_desc, tup); + CatalogTupleInsert(pg_type_desc, tup, NULL); /* * Create dependencies. We can/must skip this in bootstrap mode. @@ -229,13 +229,12 @@ TypeCreate(Oid newTypeOid, Oid typeObjectId; bool isDependentType; bool rebuildDeps = false; - Acl *typacl; + Acl *typacl = NULL; HeapTuple tup; - bool nulls[Natts_pg_type]; - bool replaces[Natts_pg_type]; - Datum values[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; NameData name; - int i; ObjectAddress address; /* @@ -334,78 +333,65 @@ TypeCreate(Oid newTypeOid, typeType == TYPTYPE_MULTIRANGE || (OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE); - /* - * initialize arrays needed for heap_form_tuple or heap_modify_tuple - */ - for (i = 0; i < Natts_pg_type; ++i) - { - nulls[i] = false; - replaces[i] = true; - values[i] = (Datum) 0; - } + HeapTupleUpdateSetAllColumnsUpdated(pg_type, updated); - /* - * insert data values - */ + /* Insert data values */ namestrcpy(&name, typeName); - values[Anum_pg_type_typname - 1] = NameGetDatum(&name); - values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace); - values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId); - values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize); - values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue); - values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType); - values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory); - values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred); - values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true); - values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim); - values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid); - values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(subscriptProcedure); - values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType); - values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType); - values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure); - values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure); - values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure); - values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure); - values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure); - values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure); - values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure); - values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment); - values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage); - values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull); - values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType); - values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod); - values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims); - values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation); + HeapTupleUpdateValue(pg_type, typname, NameGetDatum(&name), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typnamespace, ObjectIdGetDatum(typeNamespace), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typowner, ObjectIdGetDatum(ownerId), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typlen, Int16GetDatum(internalSize), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typbyval, BoolGetDatum(passedByValue), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typtype, CharGetDatum(typeType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typcategory, CharGetDatum(typeCategory), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typispreferred, BoolGetDatum(typePreferred), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typisdefined, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typdelim, CharGetDatum(typDelim), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typrelid, ObjectIdGetDatum(relationOid), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typsubscript, ObjectIdGetDatum(subscriptProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typelem, ObjectIdGetDatum(elementType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typarray, ObjectIdGetDatum(arrayType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typinput, ObjectIdGetDatum(inputProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typoutput, ObjectIdGetDatum(outputProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typreceive, ObjectIdGetDatum(receiveProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typsend, ObjectIdGetDatum(sendProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typmodin, ObjectIdGetDatum(typmodinProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typmodout, ObjectIdGetDatum(typmodoutProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typanalyze, ObjectIdGetDatum(analyzeProcedure), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typalign, CharGetDatum(alignment), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typstorage, CharGetDatum(storage), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typnotnull, BoolGetDatum(typeNotNull), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typbasetype, ObjectIdGetDatum(baseType), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typtypmod, Int32GetDatum(typeMod), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typndims, Int32GetDatum(typNDims), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typcollation, ObjectIdGetDatum(typeCollation), values, nulls, updated); /* - * initialize the default binary value for this type. Check for nulls of - * course. + * Initialize the default binary value for this type. */ if (defaultTypeBin) - values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin); + HeapTupleUpdateValue(pg_type, typdefaultbin, CStringGetTextDatum(defaultTypeBin), values, nulls, updated); else - nulls[Anum_pg_type_typdefaultbin - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated); /* - * initialize the default value for this type. + * Initialize the default value for this type. */ if (defaultTypeValue) - values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue); + HeapTupleUpdateValue(pg_type, typdefault, CStringGetTextDatum(defaultTypeValue), values, nulls, updated); else - nulls[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefault, values, nulls, updated); /* - * Initialize the type's ACL, too. But dependent types don't get one. + * Initialize the type's ACL too, but dependent types don't get one. */ - if (isDependentType) - typacl = NULL; - else - typacl = get_user_default_acl(OBJECT_TYPE, ownerId, - typeNamespace); + if (!isDependentType) + typacl = get_user_default_acl(OBJECT_TYPE, ownerId, typeNamespace); + if (typacl != NULL) - values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl); + HeapTupleUpdateValue(pg_type, typacl, PointerGetDatum(typacl), values, nulls, updated); else - nulls[Anum_pg_type_typacl - 1] = true; + HeapTupleUpdateValueNull(pg_type, typacl, values, nulls, updated); /* * open pg_type and prepare to insert or update a row. @@ -431,9 +417,7 @@ TypeCreate(Oid newTypeOid, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists", typeName))); - /* - * shell type must have been created by same owner - */ + /* Shell type must have been created by same owner */ if (typform->typowner != ownerId) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TYPE, typeName); @@ -441,18 +425,16 @@ TypeCreate(Oid newTypeOid, if (OidIsValid(newTypeOid)) elog(ERROR, "cannot assign new OID to existing shell type"); - replaces[Anum_pg_type_oid - 1] = false; + HeapTupleSetColumnNotUpdated(pg_type, oid, updated); - /* - * Okay to update existing shell type tuple - */ - tup = heap_modify_tuple(tup, + /* Okay to update existing shell type tuple */ + tup = heap_update_tuple(tup, RelationGetDescr(pg_type_desc), values, nulls, - replaces); + updated); - CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup); + CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup, updated, NULL); typeObjectId = typform->oid; @@ -480,12 +462,11 @@ TypeCreate(Oid newTypeOid, Anum_pg_type_oid); } - values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typeObjectId); + HeapTupleUpdateValue(pg_type, oid, ObjectIdGetDatum(typeObjectId), values, nulls, updated); - tup = heap_form_tuple(RelationGetDescr(pg_type_desc), - values, nulls); + tup = heap_form_tuple(RelationGetDescr(pg_type_desc), values, nulls); - CatalogTupleInsert(pg_type_desc, tup); + CatalogTupleInsert(pg_type_desc, tup, NULL); } /* @@ -509,9 +490,8 @@ TypeCreate(Oid newTypeOid, ObjectAddressSet(address, TypeRelationId, typeObjectId); - /* - * finish up - */ + /* Clean up */ + bms_free(updated); table_close(pg_type_desc, RowExclusiveLock); return address; @@ -765,6 +745,7 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace) Relation pg_type_desc; HeapTuple tuple; Form_pg_type typ; + Bitmapset *updated = NULL; Oid arrayOid; Oid oldTypeOid; @@ -804,12 +785,14 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace) } /* OK, do the rename --- tuple is a copy, so OK to scribble on it */ - namestrcpy(&(typ->typname), newTypeName); + namestrcpy(&typ->typname, newTypeName); + HeapTupleMarkColumnUpdated(pg_type, typname, updated); - CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple); + CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0); + bms_free(updated); heap_freetuple(tuple); table_close(pg_type_desc, RowExclusiveLock); diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 874a8fc89adb3..368f8e63b0b1e 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -336,14 +336,17 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, if (!IsBootstrapProcessingMode()) { + Bitmapset *updated = NULL; + /* 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; + HeapTupleUpdateField(pg_class, reltoastrelid, toast_relid, (Form_pg_class) GETSTRUCT(reltup), updated); + CatalogTupleUpdate(class_rel, &reltup->t_self, reltup, updated, NULL); - CatalogTupleUpdate(class_rel, &reltup->t_self, reltup); + bms_free(updated); } else { diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index cb75e11fced62..f5f8ec791c30a 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -180,7 +180,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name) AclResult aclresult; Datum *values; bool *nulls; - bool *replaces; + Bitmapset *updated = NULL; NameData nameattrdata; oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId)); @@ -326,15 +326,21 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name) /* Build modified tuple */ values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum)); nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool)); - replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool)); + + /* + * NOTE: We can't use the HeapTupleMarkColumnUpdated() macro here because + * 'Anum_name' isn't a table/column name, it's a index for the relation + * passed into the function as an argument. + */ namestrcpy(&nameattrdata, new_name); values[Anum_name - 1] = NameGetDatum(&nameattrdata); - replaces[Anum_name - 1] = true; - newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), - values, nulls, replaces); + updated = bms_add_member(updated, Anum_name - FirstLowInvalidHeapAttributeNumber); + + newtup = heap_update_tuple(oldtup, RelationGetDescr(rel), + values, nulls, updated); /* Perform actual update */ - CatalogTupleUpdate(rel, &oldtup->t_self, newtup); + CatalogTupleUpdate(rel, &oldtup->t_self, newtup, updated, NULL); InvokeObjectPostAlterHook(classId, objectId, 0); @@ -357,7 +363,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name) /* Release memory */ pfree(values); pfree(nulls); - pfree(replaces); + bms_free(updated); heap_freetuple(newtup); ReleaseSysCache(oldtup); @@ -705,7 +711,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid) newtup; Datum *values; bool *nulls; - bool *replaces; + Bitmapset *updated = NULL; tup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objid)); if (!HeapTupleIsValid(tup)) /* should not happen */ @@ -804,19 +810,21 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid) /* Build modified tuple */ values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum)); nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool)); - replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool)); + + /* NOTE: Don't use the HeapTupleMarkColumnUpdated() macro here either. */ values[Anum_namespace - 1] = ObjectIdGetDatum(nspOid); - replaces[Anum_namespace - 1] = true; - newtup = heap_modify_tuple(tup, RelationGetDescr(rel), - values, nulls, replaces); + updated = bms_add_member(updated, Anum_namespace - FirstLowInvalidHeapAttributeNumber); + + newtup = heap_update_tuple(tup, RelationGetDescr(rel), + values, nulls, updated); /* Perform actual update */ - CatalogTupleUpdate(rel, &tup->t_self, newtup); + CatalogTupleUpdate(rel, &tup->t_self, newtup, updated, NULL); /* Release memory */ pfree(values); pfree(nulls); - pfree(replaces); + bms_free(updated); /* update dependency to point to the new schema */ if (changeDependencyFor(classId, objid, @@ -967,7 +975,7 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId) HeapTuple newtup; Datum *values; bool *nulls; - bool *replaces; + Bitmapset *updated = NULL; /* Superusers can bypass permission checks */ if (!superuser()) @@ -1014,9 +1022,12 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId) nattrs = RelationGetNumberOfAttributes(rel); values = palloc0(nattrs * sizeof(Datum)); nulls = palloc0(nattrs * sizeof(bool)); - replaces = palloc0(nattrs * sizeof(bool)); + + /* + * NOTE: Don't use the HeapTupleMarkColumnUpdated() macro here either. + */ values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId); - replaces[Anum_owner - 1] = true; + updated = bms_add_member(updated, Anum_owner - FirstLowInvalidHeapAttributeNumber); /* * Determine the modified ACL for the new owner. This is only @@ -1032,16 +1043,21 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId) newAcl = aclnewowner(DatumGetAclP(datum), old_ownerId, new_ownerId); + + /* + * NOTE: Don't use the HeapTupleMarkColumnUpdated() macro here + * either. + */ values[Anum_acl - 1] = PointerGetDatum(newAcl); - replaces[Anum_acl - 1] = true; + updated = bms_add_member(updated, Anum_acl - FirstLowInvalidHeapAttributeNumber); } } - newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), - values, nulls, replaces); + newtup = heap_update_tuple(oldtup, RelationGetDescr(rel), + values, nulls, updated); /* Perform actual update */ - CatalogTupleUpdate(rel, &newtup->t_self, newtup); + CatalogTupleUpdate(rel, &newtup->t_self, newtup, updated, NULL); UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock); @@ -1051,7 +1067,7 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId) /* Release memory */ pfree(values); pfree(nulls); - pfree(replaces); + bms_free(updated); } else UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock); diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c index 58ed9d216cc01..2dca9051fa693 100644 --- a/src/backend/commands/amcmds.c +++ b/src/backend/commands/amcmds.c @@ -47,8 +47,8 @@ CreateAccessMethod(CreateAmStmt *stmt) ObjectAddress referenced; Oid amoid; Oid amhandler; - bool nulls[Natts_pg_am]; - Datum values[Natts_pg_am]; + Datum values[Natts_pg_am] = {0}; + bool nulls[Natts_pg_am] = {false}; HeapTuple tup; rel = table_open(AccessMethodRelationId, RowExclusiveLock); @@ -84,15 +84,14 @@ CreateAccessMethod(CreateAmStmt *stmt) memset(nulls, false, sizeof(nulls)); amoid = GetNewOidWithIndex(rel, AmOidIndexId, Anum_pg_am_oid); - values[Anum_pg_am_oid - 1] = ObjectIdGetDatum(amoid); - values[Anum_pg_am_amname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->amname)); - values[Anum_pg_am_amhandler - 1] = ObjectIdGetDatum(amhandler); - values[Anum_pg_am_amtype - 1] = CharGetDatum(stmt->amtype); + HeapTupleSetValue(pg_am, oid, ObjectIdGetDatum(amoid), values); + HeapTupleSetValue(pg_am, amname, DirectFunctionCall1(namein, CStringGetDatum(stmt->amname)), values); + HeapTupleSetValue(pg_am, amhandler, ObjectIdGetDatum(amhandler), values); + HeapTupleSetValue(pg_am, amtype, CharGetDatum(stmt->amtype), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); myself.classId = AccessMethodRelationId; diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 25089fae3e006..a412b78929daf 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -12,6 +12,7 @@ * *------------------------------------------------------------------------- */ +#include "catalog/pg_statistic_d.h" #include "postgres.h" #include @@ -1668,48 +1669,34 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) VacAttrStats *stats = vacattrstats[attno]; HeapTuple stup, oldtup; - int i, - k, + int k, n; - Datum values[Natts_pg_statistic]; - bool nulls[Natts_pg_statistic]; - bool replaces[Natts_pg_statistic]; + Datum values[Natts_pg_statistic] = {0}; + bool nulls[Natts_pg_statistic] = {false}; + Bitmapset *updated = NULL; /* Ignore attr if we weren't able to collect stats */ if (!stats->stats_valid) continue; - /* - * Construct a new pg_statistic tuple - */ - for (i = 0; i < Natts_pg_statistic; ++i) - { - nulls[i] = false; - replaces[i] = true; - } + /* Construct a new pg_statistic tuple */ + HeapTupleUpdateSetAllColumnsUpdated(pg_statistic, updated); + HeapTupleSetValue(pg_statistic, starelid, ObjectIdGetDatum(relid), values); + HeapTupleSetValue(pg_statistic, staattnum, Int16GetDatum(stats->tupattnum), values); + HeapTupleSetValue(pg_statistic, stainherit, BoolGetDatum(inh), values); + HeapTupleSetValue(pg_statistic, stanullfrac, Float4GetDatum(stats->stanullfrac), values); + HeapTupleSetValue(pg_statistic, stawidth, Int32GetDatum(stats->stawidth), values); + HeapTupleSetValue(pg_statistic, stadistinct, Float4GetDatum(stats->stadistinct), values); - values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(stats->tupattnum); - values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inh); - values[Anum_pg_statistic_stanullfrac - 1] = Float4GetDatum(stats->stanullfrac); - values[Anum_pg_statistic_stawidth - 1] = Int32GetDatum(stats->stawidth); - values[Anum_pg_statistic_stadistinct - 1] = Float4GetDatum(stats->stadistinct); - i = Anum_pg_statistic_stakind1 - 1; for (k = 0; k < STATISTIC_NUM_SLOTS; k++) - { - values[i++] = Int16GetDatum(stats->stakind[k]); /* stakindN */ - } - i = Anum_pg_statistic_staop1 - 1; + HeapTupleSetValue(pg_statistic, stakind1 + k, Int16GetDatum(stats->stakind[k]), values); + for (k = 0; k < STATISTIC_NUM_SLOTS; k++) - { - values[i++] = ObjectIdGetDatum(stats->staop[k]); /* staopN */ - } - i = Anum_pg_statistic_stacoll1 - 1; + HeapTupleSetValue(pg_statistic, staop1 + k, ObjectIdGetDatum(stats->staop[k]), values); + for (k = 0; k < STATISTIC_NUM_SLOTS; k++) - { - values[i++] = ObjectIdGetDatum(stats->stacoll[k]); /* stacollN */ - } - i = Anum_pg_statistic_stanumbers1 - 1; + HeapTupleSetValue(pg_statistic, stacoll1 + k, ObjectIdGetDatum(stats->stacoll[k]), values); + for (k = 0; k < STATISTIC_NUM_SLOTS; k++) { if (stats->stanumbers[k] != NULL) @@ -1721,15 +1708,12 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) for (n = 0; n < nnum; n++) numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]); arry = construct_array_builtin(numdatums, nnum, FLOAT4OID); - values[i++] = PointerGetDatum(arry); /* stanumbersN */ + HeapTupleSetValue(pg_statistic, stanumbers1 + k, PointerGetDatum(arry), values); } else - { - nulls[i] = true; - values[i++] = (Datum) 0; - } + HeapTupleSetFieldNull(pg_statistic, stanumbers1, (nulls + k)); } - i = Anum_pg_statistic_stavalues1 - 1; + for (k = 0; k < STATISTIC_NUM_SLOTS; k++) { if (stats->stavalues[k] != NULL) @@ -1742,12 +1726,11 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) stats->statyplen[k], stats->statypbyval[k], stats->statypalign[k]); - values[i++] = PointerGetDatum(arry); /* stavaluesN */ + HeapTupleSetValue(pg_statistic, stavalues1, PointerGetDatum(arry), (values + k)); } else { - nulls[i] = true; - values[i++] = (Datum) 0; + HeapTupleSetFieldNull(pg_statistic, stavalues1, (nulls + k)); } } @@ -1764,22 +1747,23 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) if (HeapTupleIsValid(oldtup)) { /* Yes, replace it */ - stup = heap_modify_tuple(oldtup, + stup = heap_update_tuple(oldtup, RelationGetDescr(sd), values, nulls, - replaces); + updated); ReleaseSysCache(oldtup); - CatalogTupleUpdateWithInfo(sd, &stup->t_self, stup, indstate); + CatalogTupleUpdate(sd, &stup->t_self, stup, updated, indstate); } else { /* No, insert new tuple */ stup = heap_form_tuple(RelationGetDescr(sd), values, nulls); - CatalogTupleInsertWithInfo(sd, stup, indstate); + CatalogTupleInsert(sd, stup, NULL); } heap_freetuple(stup); + bms_free(updated); } if (indstate != NULL) diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index b55221d44cd00..b596821e348f2 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -557,6 +557,7 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal) Form_pg_index indexForm; Relation pg_index; ListCell *index; + Bitmapset *updated = NULL; /* Disallow applying to a partitioned table */ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) @@ -594,16 +595,16 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal) */ if (indexForm->indisclustered) { - indexForm->indisclustered = false; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indisclustered, false, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); } else if (thisIndexOid == indexOid) { /* this was checked earlier, but let's be real sure */ if (!indexForm->indisvalid) elog(ERROR, "cannot cluster on invalid index %u", indexOid); - indexForm->indisclustered = true; - CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + HeapTupleUpdateField(pg_index, indisclustered, true, indexForm, updated); + CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple, updated, NULL); } InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0, @@ -613,6 +614,7 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal) } table_close(pg_index, RowExclusiveLock); + bms_free(updated); } /* @@ -847,6 +849,7 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb int elevel = verbose ? INFO : DEBUG2; PGRUsage ru0; char *nspname; + Bitmapset *updated = NULL; pg_rusage_init(&ru0); @@ -1016,18 +1019,19 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb RelationGetRelid(NewHeap)); relform = (Form_pg_class) GETSTRUCT(reltup); - relform->relpages = num_pages; - relform->reltuples = num_tuples; + HeapTupleUpdateField(pg_class, relpages, num_pages, relform, updated); + HeapTupleUpdateField(pg_class, reltuples, num_tuples, relform, updated); /* Don't update the stats for pg_class. See swap_relation_files. */ if (RelationGetRelid(OldHeap) != RelationRelationId) - CatalogTupleUpdate(relRelation, &reltup->t_self, reltup); + CatalogTupleUpdate(relRelation, &reltup->t_self, reltup, updated, NULL); else CacheInvalidateRelcacheByTuple(reltup); /* Clean up. */ heap_freetuple(reltup); table_close(relRelation, RowExclusiveLock); + bms_free(updated); /* Make the update visible */ CommandCounterIncrement(); @@ -1078,6 +1082,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, char swptmpchr; Oid relam1, relam2; + Bitmapset *updated1 = NULL; + Bitmapset *updated2 = NULL; /* We need writable copies of both pg_class tuples. */ relRelation = table_open(RelationRelationId, RowExclusiveLock); @@ -1107,27 +1113,27 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, Assert(!target_is_pg_class); swaptemp = relform1->relfilenode; - relform1->relfilenode = relform2->relfilenode; - relform2->relfilenode = swaptemp; + HeapTupleUpdateField(pg_class, relfilenode, relform2->relfilenode, relform1, updated1); + HeapTupleUpdateField(pg_class, relfilenode, swaptemp, relform2, updated2); swaptemp = relform1->reltablespace; - relform1->reltablespace = relform2->reltablespace; - relform2->reltablespace = swaptemp; + HeapTupleUpdateField(pg_class, reltablespace, relform2->reltablespace, relform1, updated1); + HeapTupleUpdateField(pg_class, reltablespace, swaptemp, relform2, updated2); swaptemp = relform1->relam; - relform1->relam = relform2->relam; - relform2->relam = swaptemp; + HeapTupleUpdateField(pg_class, relam, relform2->relam, relform1, updated1); + HeapTupleUpdateField(pg_class, relam, swaptemp, relform2, updated2); swptmpchr = relform1->relpersistence; - relform1->relpersistence = relform2->relpersistence; - relform2->relpersistence = swptmpchr; + HeapTupleUpdateField(pg_class, relpersistence, relform2->relpersistence, relform1, updated1); + HeapTupleUpdateField(pg_class, relpersistence, swptmpchr, relform2, updated2); /* Also swap toast links, if we're swapping by links */ if (!swap_toast_by_content) { swaptemp = relform1->reltoastrelid; - relform1->reltoastrelid = relform2->reltoastrelid; - relform2->reltoastrelid = swaptemp; + HeapTupleUpdateField(pg_class, reltoastrelid, relform2->reltoastrelid, relform1, updated1); + HeapTupleUpdateField(pg_class, reltoastrelid, swaptemp, relform2, updated2); } } else @@ -1217,8 +1223,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, { Assert(!TransactionIdIsValid(frozenXid) || TransactionIdIsNormal(frozenXid)); - relform1->relfrozenxid = frozenXid; - relform1->relminmxid = cutoffMulti; + HeapTupleUpdateField(pg_class, relfrozenxid, frozenXid, relform1, updated1); + HeapTupleUpdateField(pg_class, relminmxid, cutoffMulti, relform1, updated1); } /* swap size statistics too, since new rel has freshly-updated stats */ @@ -1229,20 +1235,20 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, int32 swap_allfrozen; swap_pages = relform1->relpages; - relform1->relpages = relform2->relpages; - relform2->relpages = swap_pages; + HeapTupleUpdateField(pg_class, relpages, relform2->relpages, relform1, updated1); + HeapTupleUpdateField(pg_class, relpages, swap_pages, relform2, updated2); swap_tuples = relform1->reltuples; - relform1->reltuples = relform2->reltuples; - relform2->reltuples = swap_tuples; + HeapTupleUpdateField(pg_class, reltuples, relform2->reltuples, relform1, updated1); + HeapTupleUpdateField(pg_class, reltuples, swap_tuples, relform2, updated2); swap_allvisible = relform1->relallvisible; - relform1->relallvisible = relform2->relallvisible; - relform2->relallvisible = swap_allvisible; + HeapTupleUpdateField(pg_class, relallvisible, relform2->relallvisible, relform1, updated1); + HeapTupleUpdateField(pg_class, relallvisible, swap_allvisible, relform2, updated2); swap_allfrozen = relform1->relallfrozen; - relform1->relallfrozen = relform2->relallfrozen; - relform2->relallfrozen = swap_allfrozen; + HeapTupleUpdateField(pg_class, relallfrozen, relform2->relallfrozen, relform1, updated1); + HeapTupleUpdateField(pg_class, relallfrozen, swap_allfrozen, relform2, updated2); } /* @@ -1256,13 +1262,11 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, */ if (!target_is_pg_class) { - CatalogIndexState indstate; + CatalogIndexState indstate = CatalogOpenIndexes(relRelation); + + CatalogTupleUpdate(relRelation, &reltup1->t_self, reltup1, updated1, indstate); + CatalogTupleUpdate(relRelation, &reltup2->t_self, reltup2, updated2, indstate); - indstate = CatalogOpenIndexes(relRelation); - CatalogTupleUpdateWithInfo(relRelation, &reltup1->t_self, reltup1, - indstate); - CatalogTupleUpdateWithInfo(relRelation, &reltup2->t_self, reltup2, - indstate); CatalogCloseIndexes(indstate); } else @@ -1435,6 +1439,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, heap_freetuple(reltup2); table_close(relRelation, RowExclusiveLock); + bms_free(updated1); + bms_free(updated2); } /* @@ -1535,6 +1541,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, Relation relRelation; HeapTuple reltup; Form_pg_class relform; + Bitmapset *updated = NULL; relRelation = table_open(RelationRelationId, RowExclusiveLock); @@ -1543,12 +1550,13 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, elog(ERROR, "cache lookup failed for relation %u", OIDOldHeap); relform = (Form_pg_class) GETSTRUCT(reltup); - relform->relfrozenxid = frozenXid; - relform->relminmxid = cutoffMulti; + HeapTupleUpdateField(pg_class, relfrozenxid, frozenXid, relform, updated); + HeapTupleUpdateField(pg_class, relminmxid, cutoffMulti, relform, updated); - CatalogTupleUpdate(relRelation, &reltup->t_self, reltup); + CatalogTupleUpdate(relRelation, &reltup->t_self, reltup, updated, NULL); table_close(relRelation, RowExclusiveLock); + bms_free(updated); } /* Destroy new heap with old filenumber */ diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index 8acbfbbeda041..ccc6da41a40dc 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -427,6 +427,7 @@ AlterCollation(AlterCollationStmt *stmt) Oid collOid; HeapTuple tup; Form_pg_collation collForm; + Bitmapset *updated = NULL; Datum datum; bool isnull; char *oldversion; @@ -468,29 +469,22 @@ AlterCollation(AlterCollationStmt *stmt) elog(ERROR, "invalid collation version change"); else if (oldversion && newversion && strcmp(newversion, oldversion) != 0) { - bool nulls[Natts_pg_collation]; - bool replaces[Natts_pg_collation]; - Datum values[Natts_pg_collation]; + bool nulls[Natts_pg_collation] = {false}; + Datum values[Natts_pg_collation] = {0}; ereport(NOTICE, (errmsg("changing version from %s to %s", oldversion, newversion))); - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); + HeapTupleUpdateValue(pg_collation, collversion, CStringGetTextDatum(newversion), values, nulls, updated); - values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion); - replaces[Anum_pg_collation_collversion - 1] = true; - - tup = heap_modify_tuple(tup, RelationGetDescr(rel), - values, nulls, replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); } else ereport(NOTICE, (errmsg("version has not changed"))); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); InvokeObjectPostAlterHook(CollationRelationId, collOid, 0); @@ -498,6 +492,7 @@ AlterCollation(AlterCollationStmt *stmt) heap_freetuple(tup); table_close(rel, NoLock); + bms_free(updated); return address; } diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 5c783cc61f1d7..55f9ff3f3d4c2 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -147,10 +147,9 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) SysScanDesc sd; HeapTuple oldtuple; HeapTuple newtuple = NULL; - Datum values[Natts_pg_description]; - bool nulls[Natts_pg_description]; - bool replaces[Natts_pg_description]; - int i; + Datum values[Natts_pg_description] = {0}; + bool nulls[Natts_pg_description] = {false}; + Bitmapset *updated = NULL; /* Reduce empty-string to NULL case */ if (comment != NULL && strlen(comment) == 0) @@ -159,15 +158,10 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) /* Prepare to form or update a tuple, if necessary */ if (comment != NULL) { - for (i = 0; i < Natts_pg_description; i++) - { - nulls[i] = false; - replaces[i] = true; - } - values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_description_classoid - 1] = ObjectIdGetDatum(classoid); - values[Anum_pg_description_objsubid - 1] = Int32GetDatum(subid); - values[Anum_pg_description_description - 1] = CStringGetTextDatum(comment); + HeapTupleUpdateValue(pg_description, objoid, ObjectIdGetDatum(oid), values, nulls, updated); + HeapTupleUpdateValue(pg_description, classoid, ObjectIdGetDatum(classoid), values, nulls, updated); + HeapTupleUpdateValue(pg_description, objsubid, Int32GetDatum(subid), values, nulls, updated); + HeapTupleUpdateValue(pg_description, description, CStringGetTextDatum(comment), values, nulls, updated); } /* Use the index to search for a matching old tuple */ @@ -198,9 +192,9 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) CatalogTupleDelete(description, &oldtuple->t_self); else { - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(description), values, - nulls, replaces); - CatalogTupleUpdate(description, &oldtuple->t_self, newtuple); + HeapTupleUpdateValue(pg_description, description, CStringGetTextDatum(comment), values, nulls, updated); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(description), values, nulls, updated); + CatalogTupleUpdate(description, &oldtuple->t_self, newtuple, updated, NULL); } break; /* Assume there can be only one match */ @@ -214,7 +208,7 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) { newtuple = heap_form_tuple(RelationGetDescr(description), values, nulls); - CatalogTupleInsert(description, newtuple); + CatalogTupleInsert(description, newtuple, NULL); } if (newtuple != NULL) @@ -223,6 +217,7 @@ CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment) /* Done */ table_close(description, NoLock); + bms_free(updated); } /* @@ -242,9 +237,9 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) SysScanDesc sd; HeapTuple oldtuple; HeapTuple newtuple = NULL; - Datum values[Natts_pg_shdescription]; - bool nulls[Natts_pg_shdescription]; - bool replaces[Natts_pg_shdescription]; + Datum values[Natts_pg_shdescription] = {0}; + bool nulls[Natts_pg_shdescription] = {false}; + Bitmapset *updated = NULL; int i; /* Reduce empty-string to NULL case */ @@ -257,11 +252,10 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) for (i = 0; i < Natts_pg_shdescription; i++) { nulls[i] = false; - replaces[i] = true; } - values[Anum_pg_shdescription_objoid - 1] = ObjectIdGetDatum(oid); - values[Anum_pg_shdescription_classoid - 1] = ObjectIdGetDatum(classoid); - values[Anum_pg_shdescription_description - 1] = CStringGetTextDatum(comment); + HeapTupleUpdateValue(pg_shdescription, objoid, ObjectIdGetDatum(oid), values, nulls, updated); + HeapTupleUpdateValue(pg_shdescription, classoid, ObjectIdGetDatum(classoid), values, nulls, updated); + HeapTupleUpdateValue(pg_shdescription, description, CStringGetTextDatum(comment), values, nulls, updated); } /* Use the index to search for a matching old tuple */ @@ -288,9 +282,9 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) CatalogTupleDelete(shdescription, &oldtuple->t_self); else { - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(shdescription), - values, nulls, replaces); - CatalogTupleUpdate(shdescription, &oldtuple->t_self, newtuple); + HeapTupleUpdateValue(pg_shdescription, description, CStringGetTextDatum(comment), values, nulls, updated); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(shdescription), values, nulls, updated); + CatalogTupleUpdate(shdescription, &oldtuple->t_self, newtuple, updated, NULL); } break; /* Assume there can be only one match */ @@ -304,7 +298,7 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) { newtuple = heap_form_tuple(RelationGetDescr(shdescription), values, nulls); - CatalogTupleInsert(shdescription, newtuple); + CatalogTupleInsert(shdescription, newtuple, NULL); } if (newtuple != NULL) @@ -313,6 +307,7 @@ CreateSharedComments(Oid oid, Oid classoid, const char *comment) /* Done */ table_close(shdescription, NoLock); + bms_free(updated); } /* diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 4d65e8c46c21a..1784a38e13b39 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -702,8 +702,8 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) volatile Oid dst_deftablespace; Relation pg_database_rel; HeapTuple tuple; - Datum new_record[Natts_pg_database] = {0}; - bool new_record_nulls[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; Oid dboid = InvalidOid; Oid datdba; ListCell *option; @@ -1457,45 +1457,44 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) (dblocprovider == COLLPROVIDER_LIBC && !dblocale)); /* Form tuple */ - new_record[Anum_pg_database_oid - 1] = ObjectIdGetDatum(dboid); - new_record[Anum_pg_database_datname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(dbname)); - new_record[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(datdba); - new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding); - new_record[Anum_pg_database_datlocprovider - 1] = CharGetDatum(dblocprovider); - new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate); - new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections); - new_record[Anum_pg_database_dathasloginevt - 1] = BoolGetDatum(src_hasloginevt); - new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit); - new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid); - new_record[Anum_pg_database_datminmxid - 1] = TransactionIdGetDatum(src_minmxid); - new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace); - new_record[Anum_pg_database_datcollate - 1] = CStringGetTextDatum(dbcollate); - new_record[Anum_pg_database_datctype - 1] = CStringGetTextDatum(dbctype); + HeapTupleSetValue(pg_database, oid, ObjectIdGetDatum(dboid), values); + HeapTupleSetValue(pg_database, datname, DirectFunctionCall1(namein, CStringGetDatum(dbname)), values); + HeapTupleSetValue(pg_database, datdba, ObjectIdGetDatum(datdba), values); + HeapTupleSetValue(pg_database, encoding, Int32GetDatum(encoding), values); + HeapTupleSetValue(pg_database, datlocprovider, CharGetDatum(dblocprovider), values); + HeapTupleSetValue(pg_database, datistemplate, BoolGetDatum(dbistemplate), values); + HeapTupleSetValue(pg_database, datallowconn, BoolGetDatum(dballowconnections), values); + HeapTupleSetValue(pg_database, dathasloginevt, BoolGetDatum(src_hasloginevt), values); + HeapTupleSetValue(pg_database, datconnlimit, Int32GetDatum(dbconnlimit), values); + HeapTupleSetValue(pg_database, datfrozenxid, TransactionIdGetDatum(src_frozenxid), values); + HeapTupleSetValue(pg_database, datminmxid, TransactionIdGetDatum(src_minmxid), values); + HeapTupleSetValue(pg_database, dattablespace, ObjectIdGetDatum(dst_deftablespace), values); + HeapTupleSetValue(pg_database, datcollate, CStringGetTextDatum(dbcollate), values); + HeapTupleSetValue(pg_database, datctype, CStringGetTextDatum(dbctype), values); if (dblocale) - new_record[Anum_pg_database_datlocale - 1] = CStringGetTextDatum(dblocale); + HeapTupleSetValue(pg_database, datlocale, CStringGetTextDatum(dblocale), values); else - new_record_nulls[Anum_pg_database_datlocale - 1] = true; + HeapTupleSetValueNull(pg_database, datlocale, values, nulls); if (dbicurules) - new_record[Anum_pg_database_daticurules - 1] = CStringGetTextDatum(dbicurules); + HeapTupleSetValue(pg_database, daticurules, CStringGetTextDatum(dbicurules), values); else - new_record_nulls[Anum_pg_database_daticurules - 1] = true; + HeapTupleSetValueNull(pg_database, daticurules, values, nulls); if (dbcollversion) - new_record[Anum_pg_database_datcollversion - 1] = CStringGetTextDatum(dbcollversion); + HeapTupleSetValue(pg_database, datcollversion, CStringGetTextDatum(dbcollversion), values); else - new_record_nulls[Anum_pg_database_datcollversion - 1] = true; + HeapTupleSetValueNull(pg_database, datcollversion, values, nulls); /* * We deliberately set datacl to default (NULL), rather than copying it * from the template database. Copying it would be a bad idea when the * owner is not the same as the template's owner. */ - new_record_nulls[Anum_pg_database_datacl - 1] = true; + HeapTupleSetValueNull(pg_database, datacl, values, nulls); tuple = heap_form_tuple(RelationGetDescr(pg_database_rel), - new_record, new_record_nulls); + values, nulls); - CatalogTupleInsert(pg_database_rel, tuple); + CatalogTupleInsert(pg_database_rel, tuple, NULL); /* * Now generate additional catalog entries associated with the new DB @@ -1909,6 +1908,7 @@ RenameDatabase(const char *oldname, const char *newname) int notherbackends; int npreparedxacts; ObjectAddress address; + Bitmapset *updated = NULL; /* * Look up the target database's OID, and get exclusive lock on it. We @@ -1980,8 +1980,9 @@ RenameDatabase(const char *oldname, const char *newname) 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, &otid, newtup); + namestrcpy(&((Form_pg_database) GETSTRUCT(newtup))->datname, newname); + HeapTupleMarkColumnUpdated(pg_database, datname, updated); + CatalogTupleUpdate(rel, &otid, newtup, updated, NULL); UnlockTuple(rel, &otid, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); @@ -1992,6 +1993,7 @@ RenameDatabase(const char *oldname, const char *newname) * Close pg_database, but keep lock till commit. */ table_close(rel, NoLock); + bms_free(updated); return address; } @@ -2189,9 +2191,9 @@ movedb(const char *dbname, const char *tblspcname) PG_ENSURE_ERROR_CLEANUP(movedb_failure_callback, PointerGetDatum(&fparms)); { - Datum new_record[Natts_pg_database] = {0}; - bool new_record_nulls[Natts_pg_database] = {0}; - bool new_record_repl[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; /* * Copy files from the old tablespace to the new one @@ -2233,13 +2235,10 @@ movedb(const char *dbname, const char *tblspcname) 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; + HeapTupleUpdateValue(pg_database, dattablespace, ObjectIdGetDatum(dst_tblspcoid), values, nulls, updated); - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(pgdbrel), - new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, RelationGetDescr(pgdbrel), values, nulls, updated); + CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple, updated, NULL); UnlockTuple(pgdbrel, &oldtuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); @@ -2267,6 +2266,7 @@ movedb(const char *dbname, const char *tblspcname) * Close pg_database, but keep lock till commit. */ table_close(pgdbrel, NoLock); + bms_free(updated); } PG_END_ENSURE_ERROR_CLEANUP(movedb_failure_callback, PointerGetDatum(&fparms)); @@ -2382,9 +2382,9 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) DefElem *dallowconnections = NULL; DefElem *dconnlimit = NULL; DefElem *dtablespace = NULL; - Datum new_record[Natts_pg_database] = {0}; - bool new_record_nulls[Natts_pg_database] = {0}; - bool new_record_repl[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; /* Extract options from the statement node tree */ foreach(option, stmt->options) @@ -2503,24 +2503,16 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) * Build an updated tuple, perusing the information just obtained */ if (distemplate) - { - new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate); - new_record_repl[Anum_pg_database_datistemplate - 1] = true; - } + HeapTupleUpdateValue(pg_database, datistemplate, BoolGetDatum(dbistemplate), values, nulls, updated); + if (dallowconnections) - { - new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections); - new_record_repl[Anum_pg_database_datallowconn - 1] = true; - } + HeapTupleUpdateValue(pg_database, datallowconn, BoolGetDatum(dballowconnections), values, nulls, updated); + if (dconnlimit) - { - new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit); - new_record_repl[Anum_pg_database_datconnlimit - 1] = true; - } + HeapTupleUpdateValue(pg_database, datconnlimit, Int32GetDatum(dbconnlimit), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(DatabaseRelationId, dboid, 0); @@ -2529,6 +2521,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel) /* Close pg_database, but keep lock till commit */ table_close(rel, NoLock); + bms_free(updated); return dboid; } @@ -2597,22 +2590,21 @@ AlterDatabaseRefreshColl(AlterDatabaseRefreshCollStmt *stmt) elog(ERROR, "invalid collation version change"); else if (oldversion && newversion && strcmp(newversion, oldversion) != 0) { - bool nulls[Natts_pg_database] = {0}; - bool replaces[Natts_pg_database] = {0}; Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; HeapTuple newtuple; ereport(NOTICE, (errmsg("changing version from %s to %s", oldversion, newversion))); - values[Anum_pg_database_datcollversion - 1] = CStringGetTextDatum(newversion); - replaces[Anum_pg_database_datcollversion - 1] = true; + HeapTupleUpdateValue(pg_database, datcollversion, CStringGetTextDatum(newversion), values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &tuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); + bms_free(updated); } else ereport(NOTICE, @@ -2699,9 +2691,9 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) */ if (datForm->datdba != newOwnerId) { - Datum repl_val[Natts_pg_database]; - bool repl_null[Natts_pg_database] = {0}; - bool repl_repl[Natts_pg_database] = {0}; + Datum values[Natts_pg_database] = {0}; + bool nulls[Natts_pg_database] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -2731,8 +2723,7 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); - repl_repl[Anum_pg_database_datdba - 1] = true; - repl_val[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_database, datdba, ObjectIdGetDatum(newOwnerId), values, nulls, updated); /* * Determine the modified ACL for the new owner. This is only @@ -2746,18 +2737,18 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), datForm->datdba, newOwnerId); - repl_repl[Anum_pg_database_datacl - 1] = true; - repl_val[Anum_pg_database_datacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_database, datacl, PointerGetDatum(newAcl), values, nulls, updated); } - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock); heap_freetuple(newtuple); /* Update owner dependency reference */ changeDependencyOnOwner(DatabaseRelationId, db_id, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0); diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index f34868da5ab94..5408e6d276027 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -280,8 +280,8 @@ insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtO Relation tgrel; Oid trigoid; HeapTuple tuple; - Datum values[Natts_pg_event_trigger]; - bool nulls[Natts_pg_event_trigger]; + Datum values[Natts_pg_event_trigger] = {0}; + bool nulls[Natts_pg_event_trigger] = {false}; NameData evtnamedata, evteventdata; ObjectAddress myself, @@ -293,25 +293,23 @@ insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtO /* Build the new pg_trigger tuple. */ trigoid = GetNewOidWithIndex(tgrel, EventTriggerOidIndexId, Anum_pg_event_trigger_oid); - values[Anum_pg_event_trigger_oid - 1] = ObjectIdGetDatum(trigoid); + HeapTupleSetValue(pg_event_trigger, oid, ObjectIdGetDatum(trigoid), values); memset(nulls, false, sizeof(nulls)); namestrcpy(&evtnamedata, trigname); - values[Anum_pg_event_trigger_evtname - 1] = NameGetDatum(&evtnamedata); + HeapTupleSetValue(pg_event_trigger, evtname, NameGetDatum(&evtnamedata), values); namestrcpy(&evteventdata, eventname); - values[Anum_pg_event_trigger_evtevent - 1] = NameGetDatum(&evteventdata); - values[Anum_pg_event_trigger_evtowner - 1] = ObjectIdGetDatum(evtOwner); - values[Anum_pg_event_trigger_evtfoid - 1] = ObjectIdGetDatum(funcoid); - values[Anum_pg_event_trigger_evtenabled - 1] = - CharGetDatum(TRIGGER_FIRES_ON_ORIGIN); + HeapTupleSetValue(pg_event_trigger, evtevent, NameGetDatum(&evteventdata), values); + HeapTupleSetValue(pg_event_trigger, evtowner, ObjectIdGetDatum(evtOwner), values); + HeapTupleSetValue(pg_event_trigger, evtfoid, ObjectIdGetDatum(funcoid), values); + HeapTupleSetValue(pg_event_trigger, evtenabled, CharGetDatum(TRIGGER_FIRES_ON_ORIGIN), values); if (taglist == NIL) - nulls[Anum_pg_event_trigger_evttags - 1] = true; + HeapTupleSetValueNull(pg_event_trigger, evttags, values, nulls); else - values[Anum_pg_event_trigger_evttags - 1] = - filter_list_to_array(taglist); + HeapTupleSetValue(pg_event_trigger, evttags, filter_list_to_array(taglist), values); /* Insert heap tuple. */ tuple = heap_form_tuple(tgrel->rd_att, values, nulls); - CatalogTupleInsert(tgrel, tuple); + CatalogTupleInsert(tgrel, tuple, NULL); heap_freetuple(tuple); /* @@ -394,6 +392,7 @@ SetDatabaseHasLoginEventTriggers(void) Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock); ItemPointerData otid; HeapTuple tuple; + Bitmapset *updated = NULL; /* * Use shared lock to prevent a conflict with EventTriggerOnLogin() trying @@ -411,8 +410,9 @@ SetDatabaseHasLoginEventTriggers(void) db = (Form_pg_database) GETSTRUCT(tuple); if (!db->dathasloginevt) { - db->dathasloginevt = true; - CatalogTupleUpdate(pg_db, &otid, tuple); + HeapTupleUpdateField(pg_database, dathasloginevt, true, db, updated); + CatalogTupleUpdate(pg_db, &otid, tuple, updated, NULL); + bms_free(updated); CommandCounterIncrement(); } UnlockTuple(pg_db, &otid, InplaceUpdateTupleLock); @@ -431,6 +431,7 @@ AlterEventTrigger(AlterEventTrigStmt *stmt) Oid trigoid; Form_pg_event_trigger evtForm; char tgenabled = stmt->tgenabled; + Bitmapset *updated = NULL; tgrel = table_open(EventTriggerRelationId, RowExclusiveLock); @@ -450,9 +451,10 @@ AlterEventTrigger(AlterEventTrigStmt *stmt) stmt->trigname); /* tuple is a copy, so we can modify it below */ - evtForm->evtenabled = tgenabled; + HeapTupleUpdateField(pg_event_trigger, evtenabled, tgenabled, evtForm, updated); - CatalogTupleUpdate(tgrel, &tup->t_self, tup); + CatalogTupleUpdate(tgrel, &tup->t_self, tup, updated, NULL); + bms_free(updated); /* * Login event triggers have an additional flag in pg_database to enable @@ -539,6 +541,7 @@ static void AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_event_trigger form; + Bitmapset *updated = NULL; form = (Form_pg_event_trigger) GETSTRUCT(tup); @@ -557,8 +560,9 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) NameStr(form->evtname)), errhint("The owner of an event trigger must be a superuser."))); - form->evtowner = newOwnerId; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_event_trigger, evtowner, newOwnerId, form, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); /* Update owner dependency reference */ changeDependencyOnOwner(EventTriggerRelationId, diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 93ef1ad106fdb..41ac7d2f9942f 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -2067,8 +2067,8 @@ InsertExtensionTuple(const char *extName, Oid extOwner, { Oid extensionOid; Relation rel; - Datum values[Natts_pg_extension]; - bool nulls[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; HeapTuple tuple; ObjectAddress myself; ObjectAddress nsp; @@ -2085,27 +2085,26 @@ InsertExtensionTuple(const char *extName, Oid extOwner, extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId, Anum_pg_extension_oid); - values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid); - values[Anum_pg_extension_extname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(extName)); - values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner); - values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid); - values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable); - values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion); + HeapTupleSetValue(pg_extension, oid, ObjectIdGetDatum(extensionOid), values); + HeapTupleSetValue(pg_extension, extname, DirectFunctionCall1(namein, CStringGetDatum(extName)), values); + HeapTupleSetValue(pg_extension, extowner, ObjectIdGetDatum(extOwner), values); + HeapTupleSetValue(pg_extension, extnamespace, ObjectIdGetDatum(schemaOid), values); + HeapTupleSetValue(pg_extension, extrelocatable, BoolGetDatum(relocatable), values); + HeapTupleSetValue(pg_extension, extversion, CStringGetTextDatum(extVersion), values); if (extConfig == PointerGetDatum(NULL)) - nulls[Anum_pg_extension_extconfig - 1] = true; + HeapTupleSetValueNull(pg_extension, extconfig, values, nulls); else - values[Anum_pg_extension_extconfig - 1] = extConfig; + HeapTupleSetValue(pg_extension, extconfig, extConfig, values); if (extCondition == PointerGetDatum(NULL)) - nulls[Anum_pg_extension_extcondition - 1] = true; + HeapTupleSetValueNull(pg_extension, extcondition, values, nulls); else - values[Anum_pg_extension_extcondition - 1] = extCondition; + HeapTupleSetValue(pg_extension, extcondition, extCondition, values); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); table_close(rel, RowExclusiveLock); @@ -2674,9 +2673,9 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) int arrayLength; int arrayIndex; bool isnull; - Datum repl_val[Natts_pg_extension]; - bool repl_null[Natts_pg_extension]; - bool repl_repl[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; + Bitmapset *updated = NULL; ArrayType *a; /* @@ -2731,10 +2730,6 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) elog(ERROR, "could not find tuple for extension %u", CurrentExtensionObject); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* Build or modify the extconfig value */ elementDatum = ObjectIdGetDatum(tableoid); @@ -2784,8 +2779,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) true /* OID's typbyval */ , TYPALIGN_INT /* OID's typalign */ ); } - repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a); - repl_repl[Anum_pg_extension_extconfig - 1] = true; + HeapTupleUpdateValue(pg_extension, extconfig, PointerGetDatum(a), values, nulls, updated); /* Build or modify the extcondition value */ elementDatum = PointerGetDatum(wherecond); @@ -2820,17 +2814,16 @@ pg_extension_config_dump(PG_FUNCTION_ARGS) false /* TEXT's typbyval */ , TYPALIGN_INT /* TEXT's typalign */ ); } - repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a); - repl_repl[Anum_pg_extension_extcondition - 1] = true; + HeapTupleUpdateValue(pg_extension, extcondition, PointerGetDatum(a), values, nulls, updated); - extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel), - repl_val, repl_null, repl_repl); + extTup = heap_update_tuple(extTup, RelationGetDescr(extRel), values, nulls, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); systable_endscan(extScan); table_close(extRel, RowExclusiveLock); + bms_free(updated); PG_RETURN_VOID(); } @@ -2906,9 +2899,9 @@ extension_config_remove(Oid extensionoid, Oid tableoid) int arrayLength; int arrayIndex; bool isnull; - Datum repl_val[Natts_pg_extension]; - bool repl_null[Natts_pg_extension]; - bool repl_repl[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; + Bitmapset *updated = NULL; ArrayType *a; /* Find the pg_extension tuple */ @@ -2975,14 +2968,10 @@ extension_config_remove(Oid extensionoid, Oid tableoid) } /* Modify or delete the extconfig value */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (arrayLength <= 1) { /* removing only element, just set array to null */ - repl_null[Anum_pg_extension_extconfig - 1] = true; + HeapTupleUpdateValueNull(pg_extension, extconfig, values, nulls, updated); } else { @@ -2999,9 +2988,8 @@ extension_config_remove(Oid extensionoid, Oid tableoid) a = construct_array_builtin(dvalues, arrayLength - 1, OIDOID); - repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a); + HeapTupleUpdateValue(pg_extension, extconfig, PointerGetDatum(a), values, nulls, updated); } - repl_repl[Anum_pg_extension_extconfig - 1] = true; /* Modify or delete the extcondition value */ arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition, @@ -3026,7 +3014,7 @@ extension_config_remove(Oid extensionoid, Oid tableoid) if (arrayLength <= 1) { /* removing only element, just set array to null */ - repl_null[Anum_pg_extension_extcondition - 1] = true; + HeapTupleUpdateValueNull(pg_extension, extcondition, values, nulls, updated); } else { @@ -3042,19 +3030,17 @@ extension_config_remove(Oid extensionoid, Oid tableoid) dvalues[i] = dvalues[i + 1]; a = construct_array_builtin(dvalues, arrayLength - 1, TEXTOID); - - repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a); + HeapTupleUpdateValue(pg_extension, extcondition, PointerGetDatum(a), values, nulls, updated); } - repl_repl[Anum_pg_extension_extcondition - 1] = true; - extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel), - repl_val, repl_null, repl_repl); + extTup = heap_update_tuple(extTup, RelationGetDescr(extRel), values, nulls, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); systable_endscan(extScan); table_close(extRel, RowExclusiveLock); + bms_free(updated); } /* @@ -3072,6 +3058,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o SysScanDesc extScan; HeapTuple extTup; Form_pg_extension extForm; + Bitmapset *updated = NULL; Relation depRel; SysScanDesc depScan; HeapTuple depTup; @@ -3253,11 +3240,12 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o relation_close(depRel, AccessShareLock); /* Now adjust pg_extension.extnamespace */ - extForm->extnamespace = nspOid; + HeapTupleUpdateField(pg_extension, extnamespace, nspOid, extForm, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); table_close(extRel, RowExclusiveLock); + bms_free(updated); /* update dependency to point to the new schema */ if (changeDependencyFor(ExtensionRelationId, extensionOid, @@ -3447,9 +3435,9 @@ ApplyExtensionUpdates(Oid extensionOid, SysScanDesc extScan; HeapTuple extTup; Form_pg_extension extForm; - Datum values[Natts_pg_extension]; - bool nulls[Natts_pg_extension]; - bool repl[Natts_pg_extension]; + Datum values[Natts_pg_extension] = {0}; + bool nulls[Natts_pg_extension] = {false}; + Bitmapset *updated = NULL; ObjectAddress myself; ListCell *lc; @@ -3486,21 +3474,14 @@ ApplyExtensionUpdates(Oid extensionOid, /* * Modify extrelocatable and extversion in the pg_extension tuple */ - memset(values, 0, sizeof(values)); - memset(nulls, 0, sizeof(nulls)); - memset(repl, 0, sizeof(repl)); - - values[Anum_pg_extension_extrelocatable - 1] = - BoolGetDatum(control->relocatable); - repl[Anum_pg_extension_extrelocatable - 1] = true; - values[Anum_pg_extension_extversion - 1] = - CStringGetTextDatum(versionName); - repl[Anum_pg_extension_extversion - 1] = true; + HeapTupleUpdateValue(pg_extension, extrelocatable, BoolGetDatum(control->relocatable), values, nulls, updated); + HeapTupleUpdateValue(pg_extension, extversion, CStringGetTextDatum(versionName), values, nulls, updated); - extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel), - values, nulls, repl); + extTup = heap_update_tuple(extTup, RelationGetDescr(extRel), + values, nulls, updated); - CatalogTupleUpdate(extRel, &extTup->t_self, extTup); + CatalogTupleUpdate(extRel, &extTup->t_self, extTup, updated, NULL); + bms_free(updated); systable_endscan(extScan); diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 536065dc515bc..571814ada29f8 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -216,9 +216,9 @@ static void AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_foreign_data_wrapper form; - Datum repl_val[Natts_pg_foreign_data_wrapper]; - bool repl_null[Natts_pg_foreign_data_wrapper]; - bool repl_repl[Natts_pg_foreign_data_wrapper]; + Datum values[Natts_pg_foreign_data_wrapper] = {0}; + bool nulls[Natts_pg_foreign_data_wrapper] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -243,11 +243,7 @@ AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerI if (form->fdwowner != newOwnerId) { - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_foreign_data_wrapper_fdwowner - 1] = true; - repl_val[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); aclDatum = heap_getattr(tup, Anum_pg_foreign_data_wrapper_fdwacl, @@ -258,19 +254,18 @@ AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerI { newAcl = aclnewowner(DatumGetAclP(aclDatum), form->fdwowner, newOwnerId); - repl_repl[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true; - repl_val[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwacl, PointerGetDatum(newAcl), values, nulls, updated); } - tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, - repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Update owner dependency reference */ changeDependencyOnOwner(ForeignDataWrapperRelationId, form->oid, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, @@ -349,9 +344,9 @@ static void AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_foreign_server form; - Datum repl_val[Natts_pg_foreign_server]; - bool repl_null[Natts_pg_foreign_server]; - bool repl_repl[Natts_pg_foreign_server]; + Datum values[Natts_pg_foreign_server] = {0}; + bool nulls[Natts_pg_foreign_server] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -386,11 +381,7 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) } } - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_foreign_server_srvowner - 1] = true; - repl_val[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_foreign_server, srvowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); aclDatum = heap_getattr(tup, Anum_pg_foreign_server_srvacl, @@ -401,18 +392,17 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), form->srvowner, newOwnerId); - repl_repl[Anum_pg_foreign_server_srvacl - 1] = true; - repl_val[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_foreign_server, srvacl, PointerGetDatum(newAcl), values, nulls, updated); } - tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, - repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Update owner dependency reference */ changeDependencyOnOwner(ForeignServerRelationId, form->oid, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(ForeignServerRelationId, @@ -569,8 +559,8 @@ ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt) { Relation rel; - Datum values[Natts_pg_foreign_data_wrapper]; - bool nulls[Natts_pg_foreign_data_wrapper]; + Datum values[Natts_pg_foreign_data_wrapper] = {0}; + bool nulls[Natts_pg_foreign_data_wrapper] = {false}; HeapTuple tuple; Oid fdwId; bool handler_given; @@ -612,20 +602,19 @@ CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt) fdwId = GetNewOidWithIndex(rel, ForeignDataWrapperOidIndexId, Anum_pg_foreign_data_wrapper_oid); - values[Anum_pg_foreign_data_wrapper_oid - 1] = ObjectIdGetDatum(fdwId); - values[Anum_pg_foreign_data_wrapper_fdwname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname)); - values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId); + HeapTupleSetValue(pg_foreign_data_wrapper, oid, ObjectIdGetDatum(fdwId), values); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwname, DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname)), values); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwowner, ObjectIdGetDatum(ownerId), values); /* Lookup handler and validator functions, if given */ parse_func_options(pstate, stmt->func_options, &handler_given, &fdwhandler, &validator_given, &fdwvalidator); - values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler); - values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwhandler, ObjectIdGetDatum(fdwhandler), values); + HeapTupleSetValue(pg_foreign_data_wrapper, fdwvalidator, ObjectIdGetDatum(fdwvalidator), values); - nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true; + HeapTupleSetValueNull(pg_foreign_data_wrapper, fdwacl, values, nulls); fdwoptions = transformGenericOptions(ForeignDataWrapperRelationId, PointerGetDatum(NULL), @@ -633,13 +622,13 @@ CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt) fdwvalidator); if (DatumGetPointer(fdwoptions) != NULL) - values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions; + HeapTupleSetValue(pg_foreign_data_wrapper, fdwoptions, fdwoptions, values); else - nulls[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true; + HeapTupleSetValueNull(pg_foreign_data_wrapper, fdwoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -687,9 +676,9 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) Relation rel; HeapTuple tp; Form_pg_foreign_data_wrapper fdwForm; - Datum repl_val[Natts_pg_foreign_data_wrapper]; - bool repl_null[Natts_pg_foreign_data_wrapper]; - bool repl_repl[Natts_pg_foreign_data_wrapper]; + Datum values[Natts_pg_foreign_data_wrapper] = {0}; + bool nulls[Natts_pg_foreign_data_wrapper] = {false}; + Bitmapset *updated = NULL; Oid fdwId; bool isnull; Datum datum; @@ -720,18 +709,13 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp); fdwId = fdwForm->oid; - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - parse_func_options(pstate, stmt->func_options, &handler_given, &fdwhandler, &validator_given, &fdwvalidator); if (handler_given) { - repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler); - repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true; + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwhandler, ObjectIdGetDatum(fdwhandler), values, nulls, updated); /* * It could be that the behavior of accessing foreign table changes @@ -743,8 +727,7 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) if (validator_given) { - repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator); - repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true; + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwvalidator, ObjectIdGetDatum(fdwvalidator), values, nulls, updated); /* * It could be that existing options for the FDW or dependent SERVER, @@ -784,18 +767,15 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum; + HeapTupleUpdateValue(pg_foreign_data_wrapper, fdwoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true; - - repl_repl[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_data_wrapper, fdwoptions, values, nulls, updated); } /* Everything looks good - update the tuple */ - tp = heap_modify_tuple(tp, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tp = heap_update_tuple(tp, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tp->t_self, tp); + CatalogTupleUpdate(rel, &tp->t_self, tp, updated, NULL); heap_freetuple(tp); @@ -837,6 +817,7 @@ AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt) InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, fdwId, 0); table_close(rel, RowExclusiveLock); + bms_free(updated); return myself; } @@ -850,8 +831,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt) { Relation rel; Datum srvoptions; - Datum values[Natts_pg_foreign_server]; - bool nulls[Natts_pg_foreign_server]; + Datum values[Natts_pg_foreign_server] = {0}; + bool nulls[Natts_pg_foreign_server] = {false}; HeapTuple tuple; Oid srvId; Oid ownerId; @@ -914,28 +895,25 @@ CreateForeignServer(CreateForeignServerStmt *stmt) srvId = GetNewOidWithIndex(rel, ForeignServerOidIndexId, Anum_pg_foreign_server_oid); - values[Anum_pg_foreign_server_oid - 1] = ObjectIdGetDatum(srvId); - values[Anum_pg_foreign_server_srvname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->servername)); - values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId); - values[Anum_pg_foreign_server_srvfdw - 1] = ObjectIdGetDatum(fdw->fdwid); + HeapTupleSetValue(pg_foreign_server, oid, ObjectIdGetDatum(srvId), values); + HeapTupleSetValue(pg_foreign_server, srvname, DirectFunctionCall1(namein, CStringGetDatum(stmt->servername)), values); + HeapTupleSetValue(pg_foreign_server, srvowner, ObjectIdGetDatum(ownerId), values); + HeapTupleSetValue(pg_foreign_server, srvfdw, ObjectIdGetDatum(fdw->fdwid), values); /* Add server type if supplied */ if (stmt->servertype) - values[Anum_pg_foreign_server_srvtype - 1] = - CStringGetTextDatum(stmt->servertype); + HeapTupleSetValue(pg_foreign_server, srvtype, CStringGetTextDatum(stmt->servertype), values); else - nulls[Anum_pg_foreign_server_srvtype - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvtype, values, nulls); /* Add server version if supplied */ if (stmt->version) - values[Anum_pg_foreign_server_srvversion - 1] = - CStringGetTextDatum(stmt->version); + HeapTupleSetValue(pg_foreign_server, srvversion, CStringGetTextDatum(stmt->version), values); else - nulls[Anum_pg_foreign_server_srvversion - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvversion, values, nulls); /* Start with a blank acl */ - nulls[Anum_pg_foreign_server_srvacl - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvacl, values, nulls); /* Add server options */ srvoptions = transformGenericOptions(ForeignServerRelationId, @@ -944,13 +922,13 @@ CreateForeignServer(CreateForeignServerStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(srvoptions) != NULL) - values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions; + HeapTupleSetValue(pg_foreign_server, srvoptions, srvoptions, values); else - nulls[Anum_pg_foreign_server_srvoptions - 1] = true; + HeapTupleSetValueNull(pg_foreign_server, srvoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -986,9 +964,9 @@ AlterForeignServer(AlterForeignServerStmt *stmt) { Relation rel; HeapTuple tp; - Datum repl_val[Natts_pg_foreign_server]; - bool repl_null[Natts_pg_foreign_server]; - bool repl_repl[Natts_pg_foreign_server]; + Datum values[Natts_pg_foreign_server] = {0}; + bool nulls[Natts_pg_foreign_server] = {false}; + Bitmapset *updated = NULL; Oid srvId; Form_pg_foreign_server srvForm; ObjectAddress address; @@ -1013,22 +991,15 @@ AlterForeignServer(AlterForeignServerStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FOREIGN_SERVER, stmt->servername); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (stmt->has_version) { /* * Change the server VERSION string. */ if (stmt->version) - repl_val[Anum_pg_foreign_server_srvversion - 1] = - CStringGetTextDatum(stmt->version); + HeapTupleUpdateValue(pg_foreign_server, srvversion, CStringGetTextDatum(stmt->version), values, nulls, updated); else - repl_null[Anum_pg_foreign_server_srvversion - 1] = true; - - repl_repl[Anum_pg_foreign_server_srvversion - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_server, srvversion, values, nulls, updated); } if (stmt->options) @@ -1052,18 +1023,15 @@ AlterForeignServer(AlterForeignServerStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum; + HeapTupleUpdateValue(pg_foreign_server, srvoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_foreign_server_srvoptions - 1] = true; - - repl_repl[Anum_pg_foreign_server_srvoptions - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_server, srvoptions, values, nulls, updated); } /* Everything looks good - update the tuple */ - tp = heap_modify_tuple(tp, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tp = heap_update_tuple(tp, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tp->t_self, tp); + CatalogTupleUpdate(rel, &tp->t_self, tp, updated, NULL); InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0); @@ -1072,6 +1040,7 @@ AlterForeignServer(AlterForeignServerStmt *stmt) heap_freetuple(tp); table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -1112,8 +1081,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt) { Relation rel; Datum useoptions; - Datum values[Natts_pg_user_mapping]; - bool nulls[Natts_pg_user_mapping]; + Datum values[Natts_pg_user_mapping] = {0}; + bool nulls[Natts_pg_user_mapping] = {false}; HeapTuple tuple; Oid useId; Oid umId; @@ -1177,9 +1146,9 @@ CreateUserMapping(CreateUserMappingStmt *stmt) umId = GetNewOidWithIndex(rel, UserMappingOidIndexId, Anum_pg_user_mapping_oid); - values[Anum_pg_user_mapping_oid - 1] = ObjectIdGetDatum(umId); - values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId); - values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid); + HeapTupleSetValue(pg_user_mapping, oid, ObjectIdGetDatum(umId), values); + HeapTupleSetValue(pg_user_mapping, umuser, ObjectIdGetDatum(useId), values); + HeapTupleSetValue(pg_user_mapping, umserver, ObjectIdGetDatum(srv->serverid), values); /* Add user options */ useoptions = transformGenericOptions(UserMappingRelationId, @@ -1188,13 +1157,13 @@ CreateUserMapping(CreateUserMappingStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(useoptions) != NULL) - values[Anum_pg_user_mapping_umoptions - 1] = useoptions; + HeapTupleSetValue(pg_user_mapping, umoptions, useoptions, values); else - nulls[Anum_pg_user_mapping_umoptions - 1] = true; + HeapTupleSetValueNull(pg_user_mapping, umoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -1238,9 +1207,9 @@ AlterUserMapping(AlterUserMappingStmt *stmt) { Relation rel; HeapTuple tp; - Datum repl_val[Natts_pg_user_mapping]; - bool repl_null[Natts_pg_user_mapping]; - bool repl_repl[Natts_pg_user_mapping]; + Datum values[Natts_pg_user_mapping] = {0}; + bool nulls[Natts_pg_user_mapping] = {false}; + Bitmapset *updated = NULL; Oid useId; Oid umId; ForeignServer *srv; @@ -1272,10 +1241,6 @@ AlterUserMapping(AlterUserMappingStmt *stmt) if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for user mapping %u", umId); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (stmt->options) { ForeignDataWrapper *fdw; @@ -1302,18 +1267,15 @@ AlterUserMapping(AlterUserMappingStmt *stmt) fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_user_mapping_umoptions - 1] = datum; + HeapTupleUpdateValue(pg_user_mapping, umoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_user_mapping_umoptions - 1] = true; - - repl_repl[Anum_pg_user_mapping_umoptions - 1] = true; + HeapTupleUpdateValueNull(pg_user_mapping, umoptions, values, nulls, updated); } /* Everything looks good - update the tuple */ - tp = heap_modify_tuple(tp, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tp = heap_update_tuple(tp, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tp->t_self, tp); + CatalogTupleUpdate(rel, &tp->t_self, tp, updated, NULL); InvokeObjectPostAlterHook(UserMappingRelationId, umId, 0); @@ -1323,6 +1285,7 @@ AlterUserMapping(AlterUserMappingStmt *stmt) heap_freetuple(tp); table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -1416,8 +1379,8 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid) { Relation ftrel; Datum ftoptions; - Datum values[Natts_pg_foreign_table]; - bool nulls[Natts_pg_foreign_table]; + Datum values[Natts_pg_foreign_table] = {0}; + bool nulls[Natts_pg_foreign_table] = {false}; HeapTuple tuple; AclResult aclresult; ObjectAddress myself; @@ -1456,8 +1419,8 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid) memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_foreign_table_ftrelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_foreign_table_ftserver - 1] = ObjectIdGetDatum(server->serverid); + HeapTupleSetValue(pg_foreign_table, ftrelid, ObjectIdGetDatum(relid), values); + HeapTupleSetValue(pg_foreign_table, ftserver, ObjectIdGetDatum(server->serverid), values); /* Add table generic options */ ftoptions = transformGenericOptions(ForeignTableRelationId, PointerGetDatum(NULL), @@ -1465,13 +1428,13 @@ CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid) fdw->fdwvalidator); if (DatumGetPointer(ftoptions) != NULL) - values[Anum_pg_foreign_table_ftoptions - 1] = ftoptions; + HeapTupleSetValue(pg_foreign_table, ftoptions, ftoptions, values); else - nulls[Anum_pg_foreign_table_ftoptions - 1] = true; + HeapTupleSetValueNull(pg_foreign_table, ftoptions, values, nulls); tuple = heap_form_tuple(ftrel->rd_att, values, nulls); - CatalogTupleInsert(ftrel, tuple); + CatalogTupleInsert(ftrel, tuple, NULL); heap_freetuple(tuple); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 0335e982b318b..b530c3aabf0e3 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -1375,6 +1375,7 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) DefElem *rows_item = NULL; DefElem *support_item = NULL; DefElem *parallel_item = NULL; + Bitmapset *updated = NULL; ObjectAddress address; rel = table_open(ProcedureRelationId, RowExclusiveLock); @@ -1489,9 +1490,8 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) Datum datum; bool isnull; ArrayType *a; - Datum repl_val[Natts_pg_proc]; - bool repl_null[Natts_pg_proc]; - bool repl_repl[Natts_pg_proc]; + Datum values[Natts_pg_proc] = {0}; + bool nulls[Natts_pg_proc] = {false}; /* extract existing proconfig setting */ datum = SysCacheGetAttr(PROCOID, tup, Anum_pg_proc_proconfig, &isnull); @@ -1501,27 +1501,19 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) a = update_proconfig_value(a, set_items); /* update the tuple */ - memset(repl_repl, false, sizeof(repl_repl)); - repl_repl[Anum_pg_proc_proconfig - 1] = true; - if (a == NULL) - { - repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0; - repl_null[Anum_pg_proc_proconfig - 1] = true; - } + HeapTupleUpdateValueNull(pg_proc, proconfig, values, nulls, updated); else - { - repl_val[Anum_pg_proc_proconfig - 1] = PointerGetDatum(a); - repl_null[Anum_pg_proc_proconfig - 1] = false; - } + HeapTupleUpdateValue(pg_proc, proconfig, PointerGetDatum(a), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), + values, nulls, updated); } /* DO NOT put more touches of procForm below here; it's now dangling. */ /* Do the update */ - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0); @@ -1838,9 +1830,9 @@ CreateTransform(CreateTransformStmt *stmt) Oid tosqlfuncid; AclResult aclresult; Form_pg_proc procstruct; - Datum values[Natts_pg_transform]; - bool nulls[Natts_pg_transform] = {0}; - bool replaces[Natts_pg_transform] = {0}; + Datum values[Natts_pg_transform] = {0}; + bool nulls[Natts_pg_transform] = {false}; + Bitmapset *updated = NULL; Oid transformid; HeapTuple tuple; HeapTuple newtuple; @@ -1941,10 +1933,10 @@ CreateTransform(CreateTransformStmt *stmt) /* * Ready to go */ - values[Anum_pg_transform_trftype - 1] = ObjectIdGetDatum(typeid); - values[Anum_pg_transform_trflang - 1] = ObjectIdGetDatum(langid); - values[Anum_pg_transform_trffromsql - 1] = ObjectIdGetDatum(fromsqlfuncid); - values[Anum_pg_transform_trftosql - 1] = ObjectIdGetDatum(tosqlfuncid); + HeapTupleUpdateValue(pg_transform, trftype, ObjectIdGetDatum(typeid), values, nulls, updated); + HeapTupleUpdateValue(pg_transform, trflang, ObjectIdGetDatum(langid), values, nulls, updated); + HeapTupleUpdateValue(pg_transform, trffromsql, ObjectIdGetDatum(fromsqlfuncid), values, nulls, updated); + HeapTupleUpdateValue(pg_transform, trftosql, ObjectIdGetDatum(tosqlfuncid), values, nulls, updated); relation = table_open(TransformRelationId, RowExclusiveLock); @@ -1962,11 +1954,8 @@ CreateTransform(CreateTransformStmt *stmt) format_type_be(typeid), stmt->lang))); - replaces[Anum_pg_transform_trffromsql - 1] = true; - replaces[Anum_pg_transform_trftosql - 1] = true; - - newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces); - CatalogTupleUpdate(relation, &newtuple->t_self, newtuple); + newtuple = heap_update_tuple(tuple, RelationGetDescr(relation), values, nulls, updated); + CatalogTupleUpdate(relation, &newtuple->t_self, newtuple, updated, NULL); transformid = form->oid; ReleaseSysCache(tuple); @@ -1976,9 +1965,9 @@ CreateTransform(CreateTransformStmt *stmt) { transformid = GetNewOidWithIndex(relation, TransformOidIndexId, Anum_pg_transform_oid); - values[Anum_pg_transform_oid - 1] = ObjectIdGetDatum(transformid); + HeapTupleUpdateValue(pg_transform, oid, ObjectIdGetDatum(transformid), values, nulls, updated); newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls); - CatalogTupleInsert(relation, newtuple); + CatalogTupleInsert(relation, newtuple, NULL); is_replace = false; } @@ -2020,6 +2009,7 @@ CreateTransform(CreateTransformStmt *stmt) InvokeObjectPostCreateHook(TransformRelationId, transformid, 0); heap_freetuple(newtuple); + bms_free(updated); table_close(relation, RowExclusiveLock); diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 5712fac36971e..26309495ba968 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1553,6 +1553,8 @@ DefineIndex(Oid tableId, Relation pg_index = table_open(IndexRelationId, RowExclusiveLock); HeapTuple tup, newtup; + Form_pg_index indexForm; + Bitmapset *updated = NULL; tup = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexRelationId)); @@ -1560,8 +1562,10 @@ DefineIndex(Oid tableId, elog(ERROR, "cache lookup failed for index %u", indexRelationId); newtup = heap_copytuple(tup); - ((Form_pg_index) GETSTRUCT(newtup))->indisvalid = false; - CatalogTupleUpdate(pg_index, &tup->t_self, newtup); + indexForm = (Form_pg_index) GETSTRUCT(newtup); + HeapTupleUpdateField(pg_index, indisvalid, false, indexForm, updated); + CatalogTupleUpdate(pg_index, &tup->t_self, newtup, updated, NULL); + bms_free(updated); ReleaseSysCache(tup); table_close(pg_index, RowExclusiveLock); heap_freetuple(newtup); @@ -4576,6 +4580,8 @@ update_relispartition(Oid relationId, bool newval) HeapTuple tup; Relation classRel; ItemPointerData otid; + Form_pg_class classForm; + Bitmapset *updated = NULL; classRel = table_open(RelationRelationId, RowExclusiveLock); tup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(relationId)); @@ -4583,8 +4589,10 @@ update_relispartition(Oid relationId, bool newval) 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, &otid, tup); + classForm = (Form_pg_class) GETSTRUCT(tup); + HeapTupleUpdateField(pg_class, relispartition, newval, classForm, updated); + CatalogTupleUpdate(classRel, &otid, tup, updated, NULL); + bms_free(updated); UnlockTuple(classRel, &otid, InplaceUpdateTupleLock); heap_freetuple(tup); table_close(classRel, RowExclusiveLock); diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index ef7c0d624f139..d4da53083734f 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -79,6 +79,7 @@ SetMatViewPopulatedState(Relation relation, bool newstate) { Relation pgrel; HeapTuple tuple; + Bitmapset *updated = NULL; Assert(relation->rd_rel->relkind == RELKIND_MATVIEW); @@ -94,12 +95,12 @@ SetMatViewPopulatedState(Relation relation, bool newstate) elog(ERROR, "cache lookup failed for relation %u", RelationGetRelid(relation)); - ((Form_pg_class) GETSTRUCT(tuple))->relispopulated = newstate; - - CatalogTupleUpdate(pgrel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relispopulated, newstate, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pgrel, &tuple->t_self, tuple, updated, NULL); heap_freetuple(tuple); table_close(pgrel, RowExclusiveLock); + bms_free(updated); /* * Advance command counter to make the updated pg_class row locally diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index a6dd8eab5186b..38648c340abad 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -246,8 +246,8 @@ CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname, Oid opfamilyoid; Relation rel; HeapTuple tup; - Datum values[Natts_pg_opfamily]; - bool nulls[Natts_pg_opfamily]; + Datum values[Natts_pg_opfamily] = {0}; + bool nulls[Natts_pg_opfamily] = {false}; NameData opfName; ObjectAddress myself, referenced; @@ -275,16 +275,16 @@ CreateOpFamily(CreateOpFamilyStmt *stmt, const char *opfname, opfamilyoid = GetNewOidWithIndex(rel, OpfamilyOidIndexId, Anum_pg_opfamily_oid); - values[Anum_pg_opfamily_oid - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_opfamily_opfmethod - 1] = ObjectIdGetDatum(amoid); + HeapTupleSetValue(pg_opfamily, oid, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_opfamily, opfmethod, ObjectIdGetDatum(amoid), values); namestrcpy(&opfName, opfname); - values[Anum_pg_opfamily_opfname - 1] = NameGetDatum(&opfName); - values[Anum_pg_opfamily_opfnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_opfamily_opfowner - 1] = ObjectIdGetDatum(GetUserId()); + HeapTupleSetValue(pg_opfamily, opfname, NameGetDatum(&opfName), values); + HeapTupleSetValue(pg_opfamily, opfnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_opfamily, opfowner, ObjectIdGetDatum(GetUserId()), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -350,8 +350,8 @@ DefineOpClass(CreateOpClassStmt *stmt) HeapTuple tup; Form_pg_am amform; IndexAmRoutine *amroutine; - Datum values[Natts_pg_opclass]; - bool nulls[Natts_pg_opclass]; + Datum values[Natts_pg_opclass] = {0}; + bool nulls[Natts_pg_opclass] = {false}; AclResult aclresult; NameData opcName; ObjectAddress myself, @@ -653,20 +653,20 @@ DefineOpClass(CreateOpClassStmt *stmt) opclassoid = GetNewOidWithIndex(rel, OpclassOidIndexId, Anum_pg_opclass_oid); - values[Anum_pg_opclass_oid - 1] = ObjectIdGetDatum(opclassoid); - values[Anum_pg_opclass_opcmethod - 1] = ObjectIdGetDatum(amoid); + HeapTupleSetValue(pg_opclass, oid, ObjectIdGetDatum(opclassoid), values); + HeapTupleSetValue(pg_opclass, opcmethod, ObjectIdGetDatum(amoid), values); namestrcpy(&opcName, opcname); - values[Anum_pg_opclass_opcname - 1] = NameGetDatum(&opcName); - values[Anum_pg_opclass_opcnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_opclass_opcowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_opclass_opcfamily - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_opclass_opcintype - 1] = ObjectIdGetDatum(typeoid); - values[Anum_pg_opclass_opcdefault - 1] = BoolGetDatum(stmt->isDefault); - values[Anum_pg_opclass_opckeytype - 1] = ObjectIdGetDatum(storageoid); + HeapTupleSetValue(pg_opclass, opcname, NameGetDatum(&opcName), values); + HeapTupleSetValue(pg_opclass, opcnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_opclass, opcowner, ObjectIdGetDatum(GetUserId()), values); + HeapTupleSetValue(pg_opclass, opcfamily, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_opclass, opcintype, ObjectIdGetDatum(typeoid), values); + HeapTupleSetValue(pg_opclass, opcdefault, BoolGetDatum(stmt->isDefault), values); + HeapTupleSetValue(pg_opclass, opckeytype, ObjectIdGetDatum(storageoid), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -1455,8 +1455,8 @@ storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *operators, bool isAdd) { Relation rel; - Datum values[Natts_pg_amop]; - bool nulls[Natts_pg_amop]; + Datum values[Natts_pg_amop] = {0}; + bool nulls[Natts_pg_amop] = {false}; HeapTuple tup; Oid entryoid; ObjectAddress myself, @@ -1496,19 +1496,19 @@ storeOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid, entryoid = GetNewOidWithIndex(rel, AccessMethodOperatorOidIndexId, Anum_pg_amop_oid); - values[Anum_pg_amop_oid - 1] = ObjectIdGetDatum(entryoid); - values[Anum_pg_amop_amopfamily - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_amop_amoplefttype - 1] = ObjectIdGetDatum(op->lefttype); - values[Anum_pg_amop_amoprighttype - 1] = ObjectIdGetDatum(op->righttype); - values[Anum_pg_amop_amopstrategy - 1] = Int16GetDatum(op->number); - values[Anum_pg_amop_amoppurpose - 1] = CharGetDatum(oppurpose); - values[Anum_pg_amop_amopopr - 1] = ObjectIdGetDatum(op->object); - values[Anum_pg_amop_amopmethod - 1] = ObjectIdGetDatum(amoid); - values[Anum_pg_amop_amopsortfamily - 1] = ObjectIdGetDatum(op->sortfamily); + HeapTupleSetValue(pg_amop, oid, ObjectIdGetDatum(entryoid), values); + HeapTupleSetValue(pg_amop, amopfamily, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_amop, amoplefttype, ObjectIdGetDatum(op->lefttype), values); + HeapTupleSetValue(pg_amop, amoprighttype, ObjectIdGetDatum(op->righttype), values); + HeapTupleSetValue(pg_amop, amopstrategy, Int16GetDatum(op->number), values); + HeapTupleSetValue(pg_amop, amoppurpose, CharGetDatum(oppurpose), values); + HeapTupleSetValue(pg_amop, amopopr, ObjectIdGetDatum(op->object), values); + HeapTupleSetValue(pg_amop, amopmethod, ObjectIdGetDatum(amoid), values); + HeapTupleSetValue(pg_amop, amopsortfamily, ObjectIdGetDatum(op->sortfamily), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); @@ -1585,8 +1585,8 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, List *procedures, bool isAdd) { Relation rel; - Datum values[Natts_pg_amproc]; - bool nulls[Natts_pg_amproc]; + Datum values[Natts_pg_amproc] = {0}; + bool nulls[Natts_pg_amproc] = {false}; HeapTuple tup; Oid entryoid; ObjectAddress myself, @@ -1623,16 +1623,16 @@ storeProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid, entryoid = GetNewOidWithIndex(rel, AccessMethodProcedureOidIndexId, Anum_pg_amproc_oid); - values[Anum_pg_amproc_oid - 1] = ObjectIdGetDatum(entryoid); - values[Anum_pg_amproc_amprocfamily - 1] = ObjectIdGetDatum(opfamilyoid); - values[Anum_pg_amproc_amproclefttype - 1] = ObjectIdGetDatum(proc->lefttype); - values[Anum_pg_amproc_amprocrighttype - 1] = ObjectIdGetDatum(proc->righttype); - values[Anum_pg_amproc_amprocnum - 1] = Int16GetDatum(proc->number); - values[Anum_pg_amproc_amproc - 1] = ObjectIdGetDatum(proc->object); + HeapTupleSetValue(pg_amproc, oid, ObjectIdGetDatum(entryoid), values); + HeapTupleSetValue(pg_amproc, amprocfamily, ObjectIdGetDatum(opfamilyoid), values); + HeapTupleSetValue(pg_amproc, amproclefttype, ObjectIdGetDatum(proc->lefttype), values); + HeapTupleSetValue(pg_amproc, amprocrighttype, ObjectIdGetDatum(proc->righttype), values); + HeapTupleSetValue(pg_amproc, amprocnum, Int16GetDatum(proc->number), values); + HeapTupleSetValue(pg_amproc, amproc, ObjectIdGetDatum(proc->object), values); tup = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c index 673648f1fc6f5..649c37b80ae1f 100644 --- a/src/backend/commands/operatorcmds.c +++ b/src/backend/commands/operatorcmds.c @@ -466,11 +466,9 @@ AlterOperator(AlterOperatorStmt *stmt) Relation catalog; HeapTuple tup; Form_pg_operator oprForm; - int i; ListCell *pl; - Datum values[Natts_pg_operator]; - bool nulls[Natts_pg_operator]; - bool replaces[Natts_pg_operator]; + Datum values[Natts_pg_operator] = {0}; + bool nulls[Natts_pg_operator] = {false}; List *restrictionName = NIL; /* optional restrict. sel. function */ bool updateRestriction = false; Oid restrictionOid; @@ -485,6 +483,7 @@ AlterOperator(AlterOperatorStmt *stmt) bool updateMerges = false; bool canHash = false; bool updateHashes = false; + Bitmapset *updated = NULL; /* Look up the operator */ oprId = LookupOperWithArgs(stmt->opername, false); @@ -646,47 +645,27 @@ AlterOperator(AlterOperatorStmt *stmt) canHash); /* Update the tuple */ - for (i = 0; i < Natts_pg_operator; ++i) - { - values[i] = (Datum) 0; - replaces[i] = false; - nulls[i] = false; - } if (updateRestriction) - { - replaces[Anum_pg_operator_oprrest - 1] = true; - values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionOid); - } + HeapTupleUpdateValue(pg_operator, oprrest, ObjectIdGetDatum(restrictionOid), values, nulls, updated); + if (updateJoin) - { - replaces[Anum_pg_operator_oprjoin - 1] = true; - values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinOid); - } + HeapTupleUpdateValue(pg_operator, oprjoin, ObjectIdGetDatum(joinOid), values, nulls, updated); + if (OidIsValid(commutatorOid)) - { - replaces[Anum_pg_operator_oprcom - 1] = true; - values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorOid); - } + HeapTupleUpdateValue(pg_operator, oprcom, ObjectIdGetDatum(commutatorOid), values, nulls, updated); + if (OidIsValid(negatorOid)) - { - replaces[Anum_pg_operator_oprnegate - 1] = true; - values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorOid); - } + HeapTupleUpdateValue(pg_operator, oprnegate, ObjectIdGetDatum(negatorOid), values, nulls, updated); + if (updateMerges) - { - replaces[Anum_pg_operator_oprcanmerge - 1] = true; - values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge); - } + HeapTupleUpdateValue(pg_operator, oprcanmerge, BoolGetDatum(canMerge), values, nulls, updated); + if (updateHashes) - { - replaces[Anum_pg_operator_oprcanhash - 1] = true; - values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash); - } + HeapTupleUpdateValue(pg_operator, oprcanhash, BoolGetDatum(canHash), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(catalog), - values, nulls, replaces); + tup = heap_update_tuple(tup, RelationGetDescr(catalog), values, nulls, updated); - CatalogTupleUpdate(catalog, &tup->t_self, tup); + CatalogTupleUpdate(catalog, &tup->t_self, tup, updated, NULL); address = makeOperatorDependencies(tup, false, true); @@ -696,6 +675,7 @@ AlterOperator(AlterOperatorStmt *stmt) InvokeObjectPostAlterHook(OperatorRelationId, oprId, 0); table_close(catalog, NoLock); + bms_free(updated); return address; } diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index 83056960fe47e..10c7857ade5cb 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -427,6 +427,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id) Datum *role_oids; bool attr_isnull; bool keep_policy = true; + Bitmapset *updated = NULL; int i, j; @@ -483,29 +484,19 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id) if (num_roles > 0) { ArrayType *role_ids; - Datum values[Natts_pg_policy]; - bool isnull[Natts_pg_policy]; - bool replaces[Natts_pg_policy]; + Datum values[Natts_pg_policy] = {0}; + bool nulls[Natts_pg_policy] = {false}; HeapTuple new_tuple; HeapTuple reltup; ObjectAddress target; ObjectAddress myself; - /* zero-clear */ - memset(values, 0, sizeof(values)); - memset(replaces, 0, sizeof(replaces)); - memset(isnull, 0, sizeof(isnull)); - /* This is the array for the new tuple */ role_ids = construct_array_builtin(role_oids, num_roles, OIDOID); - replaces[Anum_pg_policy_polroles - 1] = true; - values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids); - - new_tuple = heap_modify_tuple(tuple, - RelationGetDescr(pg_policy_rel), - values, isnull, replaces); - CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple); + HeapTupleUpdateValue(pg_policy, polroles, PointerGetDatum(role_ids), values, nulls, updated); + new_tuple = heap_update_tuple(tuple, RelationGetDescr(pg_policy_rel), values, nulls, updated); + CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple, updated, NULL); /* Remove all the old shared dependencies (roles) */ deleteSharedDependencyRecordsFor(PolicyRelationId, policy_id, 0); @@ -552,8 +543,8 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id) } /* Clean up. */ + bms_free(updated); systable_endscan(sscan); - table_close(pg_policy_rel, RowExclusiveLock); return keep_policy; @@ -584,8 +575,8 @@ CreatePolicy(CreatePolicyStmt *stmt) ScanKeyData skey[2]; SysScanDesc sscan; HeapTuple policy_tuple; - Datum values[Natts_pg_policy]; - bool isnull[Natts_pg_policy]; + Datum values[Natts_pg_policy] = {0}; + bool nulls[Natts_pg_policy] = {false}; ObjectAddress target; ObjectAddress myself; int i; @@ -619,10 +610,6 @@ CreatePolicy(CreatePolicyStmt *stmt) qual_pstate = make_parsestate(NULL); with_check_pstate = make_parsestate(NULL); - /* zero-clear */ - memset(values, 0, sizeof(values)); - memset(isnull, 0, sizeof(isnull)); - /* Get id of table. Also handles permissions checks. */ table_id = RangeVarGetRelidExtended(stmt->table, AccessExclusiveLock, 0, @@ -688,30 +675,29 @@ CreatePolicy(CreatePolicyStmt *stmt) policy_id = GetNewOidWithIndex(pg_policy_rel, PolicyOidIndexId, Anum_pg_policy_oid); - values[Anum_pg_policy_oid - 1] = ObjectIdGetDatum(policy_id); - values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id); - values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein, - CStringGetDatum(stmt->policy_name)); - values[Anum_pg_policy_polcmd - 1] = CharGetDatum(polcmd); - values[Anum_pg_policy_polpermissive - 1] = BoolGetDatum(stmt->permissive); - values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids); + HeapTupleSetValue(pg_policy, oid, ObjectIdGetDatum(policy_id), values); + HeapTupleSetValue(pg_policy, polrelid, ObjectIdGetDatum(table_id), values); + HeapTupleSetValue(pg_policy, polname, DirectFunctionCall1(namein, + CStringGetDatum(stmt->policy_name)), values); + HeapTupleSetValue(pg_policy, polcmd, CharGetDatum(polcmd), values); + HeapTupleSetValue(pg_policy, polpermissive, BoolGetDatum(stmt->permissive), values); + HeapTupleSetValue(pg_policy, polroles, PointerGetDatum(role_ids), values); /* Add qual if present. */ if (qual) - values[Anum_pg_policy_polqual - 1] = CStringGetTextDatum(nodeToString(qual)); + HeapTupleSetValue(pg_policy, polqual, CStringGetTextDatum(nodeToString(qual)), values); else - isnull[Anum_pg_policy_polqual - 1] = true; + HeapTupleSetValueNull(pg_policy, polqual, values, nulls); /* Add WITH CHECK qual if present */ if (with_check_qual) - values[Anum_pg_policy_polwithcheck - 1] = CStringGetTextDatum(nodeToString(with_check_qual)); + HeapTupleSetValue(pg_policy, polwithcheck, CStringGetTextDatum(nodeToString(with_check_qual)), values); else - isnull[Anum_pg_policy_polwithcheck - 1] = true; + HeapTupleSetValueNull(pg_policy, polwithcheck, values, nulls); - policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values, - isnull); + policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values, nulls); - CatalogTupleInsert(pg_policy_rel, policy_tuple); + CatalogTupleInsert(pg_policy_rel, policy_tuple, NULL); /* Record Dependencies */ target.classId = RelationRelationId; @@ -782,9 +768,9 @@ AlterPolicy(AlterPolicyStmt *stmt) SysScanDesc sscan; HeapTuple policy_tuple; HeapTuple new_tuple; - Datum values[Natts_pg_policy]; - bool isnull[Natts_pg_policy]; - bool replaces[Natts_pg_policy]; + Datum values[Natts_pg_policy] = {0}; + bool nulls[Natts_pg_policy] = {false}; + Bitmapset *updated = NULL; ObjectAddress target; ObjectAddress myself; Datum polcmd_datum; @@ -854,11 +840,6 @@ AlterPolicy(AlterPolicyStmt *stmt) free_parsestate(with_check_pstate); } - /* zero-clear */ - memset(values, 0, sizeof(values)); - memset(replaces, 0, sizeof(replaces)); - memset(isnull, 0, sizeof(isnull)); - /* Find policy to update. */ pg_policy_rel = table_open(PolicyRelationId, RowExclusiveLock); @@ -918,8 +899,7 @@ AlterPolicy(AlterPolicyStmt *stmt) if (role_ids != NULL) { - replaces[Anum_pg_policy_polroles - 1] = true; - values[Anum_pg_policy_polroles - 1] = PointerGetDatum(role_ids); + HeapTupleUpdateValue(pg_policy, polroles, PointerGetDatum(role_ids), values, nulls, updated); } else { @@ -953,9 +933,7 @@ AlterPolicy(AlterPolicyStmt *stmt) if (qual != NULL) { - replaces[Anum_pg_policy_polqual - 1] = true; - values[Anum_pg_policy_polqual - 1] - = CStringGetTextDatum(nodeToString(qual)); + HeapTupleUpdateValue(pg_policy, polqual, CStringGetTextDatum(nodeToString(qual)), values, nulls, updated); } else { @@ -995,9 +973,7 @@ AlterPolicy(AlterPolicyStmt *stmt) if (with_check_qual != NULL) { - replaces[Anum_pg_policy_polwithcheck - 1] = true; - values[Anum_pg_policy_polwithcheck - 1] - = CStringGetTextDatum(nodeToString(with_check_qual)); + HeapTupleUpdateValue(pg_policy, polwithcheck, CStringGetTextDatum(nodeToString(with_check_qual)), values, nulls, updated); } else { @@ -1036,10 +1012,10 @@ AlterPolicy(AlterPolicyStmt *stmt) } } - new_tuple = heap_modify_tuple(policy_tuple, + new_tuple = heap_update_tuple(policy_tuple, RelationGetDescr(pg_policy_rel), - values, isnull, replaces); - CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple); + values, nulls, updated); + CatalogTupleUpdate(pg_policy_rel, &new_tuple->t_self, new_tuple, updated, NULL); /* Update Dependencies. */ deleteDependencyRecordsFor(PolicyRelationId, policy_id, false); @@ -1081,6 +1057,7 @@ AlterPolicy(AlterPolicyStmt *stmt) CacheInvalidateRelcache(target_table); /* Clean up. */ + bms_free(updated); systable_endscan(sscan); relation_close(target_table, NoLock); table_close(pg_policy_rel, RowExclusiveLock); @@ -1102,6 +1079,8 @@ rename_policy(RenameStmt *stmt) ScanKeyData skey[2]; SysScanDesc sscan; HeapTuple policy_tuple; + Form_pg_policy polform; + Bitmapset *updated = NULL; ObjectAddress address; /* Get id of table. Also handles permissions checks. */ @@ -1169,11 +1148,12 @@ rename_policy(RenameStmt *stmt) opoloid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid; policy_tuple = heap_copytuple(policy_tuple); + polform = (Form_pg_policy) GETSTRUCT(policy_tuple); + namestrcpy(&polform->polname, stmt->newname); + HeapTupleMarkColumnUpdated(pg_policy, polname, updated); - namestrcpy(&((Form_pg_policy) GETSTRUCT(policy_tuple))->polname, - stmt->newname); - - CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple); + CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(PolicyRelationId, opoloid, 0); diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index d75e2fa74b297..1eab77755370f 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -46,9 +46,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) Oid funcargtypes[1]; Relation rel; TupleDesc tupDesc; - Datum values[Natts_pg_language]; - bool nulls[Natts_pg_language]; - bool replaces[Natts_pg_language]; + Datum values[Natts_pg_language] = {0}; + bool nulls[Natts_pg_language] = {false}; + Bitmapset *updated = NULL; NameData langname; HeapTuple oldtup; HeapTuple tup; @@ -104,19 +104,15 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) tupDesc = RelationGetDescr(rel); /* Prepare data to be inserted */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, true, sizeof(replaces)); - namestrcpy(&langname, languageName); - values[Anum_pg_language_lanname - 1] = NameGetDatum(&langname); - values[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(languageOwner); - values[Anum_pg_language_lanispl - 1] = BoolGetDatum(true); - values[Anum_pg_language_lanpltrusted - 1] = BoolGetDatum(stmt->pltrusted); - values[Anum_pg_language_lanplcallfoid - 1] = ObjectIdGetDatum(handlerOid); - values[Anum_pg_language_laninline - 1] = ObjectIdGetDatum(inlineOid); - values[Anum_pg_language_lanvalidator - 1] = ObjectIdGetDatum(valOid); - nulls[Anum_pg_language_lanacl - 1] = true; + HeapTupleUpdateValue(pg_language, lanname, NameGetDatum(&langname), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanowner, ObjectIdGetDatum(languageOwner), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanispl, BoolGetDatum(true), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanpltrusted, BoolGetDatum(stmt->pltrusted), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanplcallfoid, ObjectIdGetDatum(handlerOid), values, nulls, updated); + HeapTupleUpdateValue(pg_language, laninline, ObjectIdGetDatum(inlineOid), values, nulls, updated); + HeapTupleUpdateValue(pg_language, lanvalidator, ObjectIdGetDatum(valOid), values, nulls, updated); + HeapTupleUpdateValueNull(pg_language, lanacl, values, nulls, updated); /* Check for pre-existing definition */ oldtup = SearchSysCache1(LANGNAME, PointerGetDatum(languageName)); @@ -142,13 +138,13 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) * Do not change existing oid, ownership or permissions. Note * dependency-update code below has to agree with this decision. */ - replaces[Anum_pg_language_oid - 1] = false; - replaces[Anum_pg_language_lanowner - 1] = false; - replaces[Anum_pg_language_lanacl - 1] = false; + HeapTupleSetColumnNotUpdated(pg_language, oid, updated); + HeapTupleSetColumnNotUpdated(pg_language, lanowner, updated); + HeapTupleSetColumnNotUpdated(pg_language, lanacl, updated); /* Okay, do it... */ - tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(oldtup, tupDesc, values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); langoid = oldform->oid; ReleaseSysCache(oldtup); @@ -157,11 +153,10 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) else { /* Creating a new language */ - langoid = GetNewOidWithIndex(rel, LanguageOidIndexId, - Anum_pg_language_oid); - values[Anum_pg_language_oid - 1] = ObjectIdGetDatum(langoid); + langoid = GetNewOidWithIndex(rel, LanguageOidIndexId, Anum_pg_language_oid); + HeapTupleUpdateValue(pg_language, oid, ObjectIdGetDatum(langoid), values, nulls, updated); tup = heap_form_tuple(tupDesc, values, nulls); - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); is_update = false; } @@ -213,6 +208,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) InvokeObjectPostCreateHook(LanguageRelationId, myself.objectId, 0); table_close(rel, RowExclusiveLock); + bms_free(updated); return myself; } diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index 1faf3a8c37283..fefce1e394c30 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -828,8 +828,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) Relation rel; ObjectAddress myself; Oid puboid; - bool nulls[Natts_pg_publication]; - Datum values[Natts_pg_publication]; + Datum values[Natts_pg_publication] = {0}; + bool nulls[Natts_pg_publication] = {false}; HeapTuple tup; bool publish_given; PublicationActions pubactions; @@ -871,9 +871,8 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_publication_pubname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname)); - values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId()); + HeapTupleSetValue(pg_publication, pubname, DirectFunctionCall1(namein, CStringGetDatum(stmt->pubname)), values); + HeapTupleSetValue(pg_publication, pubowner, ObjectIdGetDatum(GetUserId()), values); parse_publication_options(pstate, stmt->options, @@ -892,28 +891,20 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt) puboid = GetNewOidWithIndex(rel, PublicationObjectIndexId, Anum_pg_publication_oid); - values[Anum_pg_publication_oid - 1] = ObjectIdGetDatum(puboid); - values[Anum_pg_publication_puballtables - 1] = - BoolGetDatum(stmt->for_all_tables); - values[Anum_pg_publication_puballsequences - 1] = - BoolGetDatum(stmt->for_all_sequences); - values[Anum_pg_publication_pubinsert - 1] = - BoolGetDatum(pubactions.pubinsert); - values[Anum_pg_publication_pubupdate - 1] = - BoolGetDatum(pubactions.pubupdate); - values[Anum_pg_publication_pubdelete - 1] = - BoolGetDatum(pubactions.pubdelete); - values[Anum_pg_publication_pubtruncate - 1] = - BoolGetDatum(pubactions.pubtruncate); - values[Anum_pg_publication_pubviaroot - 1] = - BoolGetDatum(publish_via_partition_root); - values[Anum_pg_publication_pubgencols - 1] = - CharGetDatum(publish_generated_columns); + HeapTupleSetValue(pg_publication, oid, ObjectIdGetDatum(puboid), values); + HeapTupleSetValue(pg_publication, puballtables, BoolGetDatum(stmt->for_all_tables), values); + HeapTupleSetValue(pg_publication, puballsequences, BoolGetDatum(stmt->for_all_sequences), values); + HeapTupleSetValue(pg_publication, pubinsert, BoolGetDatum(pubactions.pubinsert), values); + HeapTupleSetValue(pg_publication, pubupdate, BoolGetDatum(pubactions.pubupdate), values); + HeapTupleSetValue(pg_publication, pubdelete, BoolGetDatum(pubactions.pubdelete), values); + HeapTupleSetValue(pg_publication, pubtruncate, BoolGetDatum(pubactions.pubtruncate), values); + HeapTupleSetValue(pg_publication, pubviaroot, BoolGetDatum(publish_via_partition_root), values); + HeapTupleSetValue(pg_publication, pubgencols, CharGetDatum(publish_generated_columns), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); recordDependencyOnOwner(PublicationRelationId, puboid, GetUserId()); @@ -991,9 +982,9 @@ static void AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, Relation rel, HeapTuple tup) { - bool nulls[Natts_pg_publication]; - bool replaces[Natts_pg_publication]; - Datum values[Natts_pg_publication]; + Datum values[Natts_pg_publication] = {0}; + bool nulls[Natts_pg_publication] = {false}; + Bitmapset *updated = NULL; bool publish_given; PublicationActions pubactions; bool publish_via_partition_root_given; @@ -1103,42 +1094,25 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt, } /* Everything ok, form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - if (publish_given) { - values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(pubactions.pubinsert); - replaces[Anum_pg_publication_pubinsert - 1] = true; - - values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(pubactions.pubupdate); - replaces[Anum_pg_publication_pubupdate - 1] = true; - - values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(pubactions.pubdelete); - replaces[Anum_pg_publication_pubdelete - 1] = true; - - values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(pubactions.pubtruncate); - replaces[Anum_pg_publication_pubtruncate - 1] = true; + HeapTupleUpdateValue(pg_publication, pubinsert, BoolGetDatum(pubactions.pubinsert), values, nulls, updated); + HeapTupleUpdateValue(pg_publication, pubupdate, BoolGetDatum(pubactions.pubupdate), values, nulls, updated); + HeapTupleUpdateValue(pg_publication, pubdelete, BoolGetDatum(pubactions.pubdelete), values, nulls, updated); + HeapTupleUpdateValue(pg_publication, pubtruncate, BoolGetDatum(pubactions.pubtruncate), values, nulls, updated); } if (publish_via_partition_root_given) - { - values[Anum_pg_publication_pubviaroot - 1] = BoolGetDatum(publish_via_partition_root); - replaces[Anum_pg_publication_pubviaroot - 1] = true; - } + HeapTupleUpdateValue(pg_publication, pubviaroot, BoolGetDatum(publish_via_partition_root), values, nulls, updated); if (publish_generated_columns_given) - { - values[Anum_pg_publication_pubgencols - 1] = CharGetDatum(publish_generated_columns); - replaces[Anum_pg_publication_pubgencols - 1] = true; - } + HeapTupleUpdateValue(pg_publication, pubgencols, CharGetDatum(publish_generated_columns), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); /* Update the catalog. */ - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); CommandCounterIncrement(); @@ -2043,6 +2017,7 @@ static void AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_publication form; + Bitmapset *updated = NULL; form = (Form_pg_publication) GETSTRUCT(tup); @@ -2079,8 +2054,10 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) } } - form->pubowner = newOwnerId; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_publication, pubowner, newOwnerId, form, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + + bms_free(updated); /* Update owner dependency reference */ changeDependencyOnOwner(PublicationRelationId, diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 3cc1472103a7a..460e2b21fc93c 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -255,6 +255,7 @@ RenameSchema(const char *oldname, const char *newname) AclResult aclresult; ObjectAddress address; Form_pg_namespace nspform; + Bitmapset *updated = NULL; rel = table_open(NamespaceRelationId, RowExclusiveLock); @@ -292,7 +293,8 @@ RenameSchema(const char *oldname, const char *newname) /* rename */ namestrcpy(&nspform->nspname, newname); - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleMarkColumnUpdated(pg_namespace, nspname, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); InvokeObjectPostAlterHook(NamespaceRelationId, nspOid, 0); @@ -300,6 +302,7 @@ RenameSchema(const char *oldname, const char *newname) table_close(rel, NoLock); heap_freetuple(tup); + bms_free(updated); return address; } @@ -374,14 +377,14 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId) */ if (nspForm->nspowner != newOwnerId) { - Datum repl_val[Natts_pg_namespace]; - bool repl_null[Natts_pg_namespace]; - bool repl_repl[Natts_pg_namespace]; + Datum values[Natts_pg_namespace] = {0}; + bool nulls[Natts_pg_namespace] = {false}; Acl *newAcl; Datum aclDatum; bool isNull; HeapTuple newtuple; AclResult aclresult; + Bitmapset *updated = NULL; /* Otherwise, must be owner of the existing object */ if (!object_ownercheck(NamespaceRelationId, nspForm->oid, GetUserId())) @@ -406,11 +409,7 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId) aclcheck_error(aclresult, OBJECT_DATABASE, get_database_name(MyDatabaseId)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_namespace_nspowner - 1] = true; - repl_val[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_namespace, nspowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); /* * Determine the modified ACL for the new owner. This is only @@ -423,19 +422,19 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), nspForm->nspowner, newOwnerId); - repl_repl[Anum_pg_namespace_nspacl - 1] = true; - repl_val[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_namespace, nspacl, PointerGetDatum(newAcl), values, nulls, updated); } - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); heap_freetuple(newtuple); /* Update owner dependency reference */ changeDependencyOnOwner(NamespaceRelationId, nspForm->oid, newOwnerId); + bms_free(updated); } InvokeObjectPostAlterHook(NamespaceRelationId, diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c index cee5d7bbb9c7e..903e3e151d5d7 100644 --- a/src/backend/commands/seclabel.c +++ b/src/backend/commands/seclabel.c @@ -334,18 +334,16 @@ SetSharedSecurityLabel(const ObjectAddress *object, SysScanDesc scan; HeapTuple oldtup; HeapTuple newtup = NULL; - Datum values[Natts_pg_shseclabel]; - bool nulls[Natts_pg_shseclabel]; - bool replaces[Natts_pg_shseclabel]; + Datum values[Natts_pg_shseclabel] = {0}; + bool nulls[Natts_pg_shseclabel] = {false}; + Bitmapset *updated = NULL; /* Prepare to form or update a tuple, if necessary. */ - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId); - values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId); - values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider); + HeapTupleUpdateValue(pg_shseclabel, objoid, ObjectIdGetDatum(object->objectId), values, nulls, updated); + HeapTupleUpdateValue(pg_shseclabel, classoid, ObjectIdGetDatum(object->classId), values, nulls, updated); + HeapTupleUpdateValue(pg_shseclabel, provider, CStringGetTextDatum(provider), values, nulls, updated); if (label != NULL) - values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label); + HeapTupleUpdateValue(pg_shseclabel, label, CStringGetTextDatum(label), values, nulls, updated); /* Use the index to search for a matching old tuple */ ScanKeyInit(&keys[0], @@ -373,10 +371,9 @@ SetSharedSecurityLabel(const ObjectAddress *object, CatalogTupleDelete(pg_shseclabel, &oldtup->t_self); else { - replaces[Anum_pg_shseclabel_label - 1] = true; - newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel), - values, nulls, replaces); - CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup); + HeapTupleUpdateValue(pg_shseclabel, label, CStringGetTextDatum(label), values, nulls, updated); + newtup = heap_update_tuple(oldtup, RelationGetDescr(pg_shseclabel), values, nulls, updated); + CatalogTupleUpdate(pg_shseclabel, &oldtup->t_self, newtup, updated, NULL); } } systable_endscan(scan); @@ -386,13 +383,14 @@ SetSharedSecurityLabel(const ObjectAddress *object, { newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel), values, nulls); - CatalogTupleInsert(pg_shseclabel, newtup); + CatalogTupleInsert(pg_shseclabel, newtup, NULL); } if (newtup != NULL) heap_freetuple(newtup); table_close(pg_shseclabel, RowExclusiveLock); + bms_free(updated); } /* @@ -409,9 +407,9 @@ SetSecurityLabel(const ObjectAddress *object, SysScanDesc scan; HeapTuple oldtup; HeapTuple newtup = NULL; - Datum values[Natts_pg_seclabel]; - bool nulls[Natts_pg_seclabel]; - bool replaces[Natts_pg_seclabel]; + Datum values[Natts_pg_seclabel] = {0}; + bool nulls[Natts_pg_seclabel] = {false}; + Bitmapset *updated = NULL; /* Shared objects have their own security label catalog. */ if (IsSharedRelation(object->classId)) @@ -421,14 +419,12 @@ SetSecurityLabel(const ObjectAddress *object, } /* Prepare to form or update a tuple, if necessary. */ - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - values[Anum_pg_seclabel_objoid - 1] = ObjectIdGetDatum(object->objectId); - values[Anum_pg_seclabel_classoid - 1] = ObjectIdGetDatum(object->classId); - values[Anum_pg_seclabel_objsubid - 1] = Int32GetDatum(object->objectSubId); - values[Anum_pg_seclabel_provider - 1] = CStringGetTextDatum(provider); + HeapTupleUpdateValue(pg_seclabel, objoid, ObjectIdGetDatum(object->objectId), values, nulls, updated); + HeapTupleUpdateValue(pg_seclabel, classoid, ObjectIdGetDatum(object->classId), values, nulls, updated); + HeapTupleUpdateValue(pg_seclabel, objsubid, Int32GetDatum(object->objectSubId), values, nulls, updated); + HeapTupleUpdateValue(pg_seclabel, provider, CStringGetTextDatum(provider), values, nulls, updated); if (label != NULL) - values[Anum_pg_seclabel_label - 1] = CStringGetTextDatum(label); + HeapTupleUpdateValue(pg_seclabel, label, CStringGetTextDatum(label), values, nulls, updated); /* Use the index to search for a matching old tuple */ ScanKeyInit(&keys[0], @@ -460,10 +456,9 @@ SetSecurityLabel(const ObjectAddress *object, CatalogTupleDelete(pg_seclabel, &oldtup->t_self); else { - replaces[Anum_pg_seclabel_label - 1] = true; - newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel), - values, nulls, replaces); - CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup); + HeapTupleUpdateValue(pg_seclabel, label, CStringGetTextDatum(label), values, nulls, updated); + newtup = heap_update_tuple(oldtup, RelationGetDescr(pg_seclabel), values, nulls, updated); + CatalogTupleUpdate(pg_seclabel, &oldtup->t_self, newtup, updated, NULL); } } systable_endscan(scan); @@ -471,9 +466,8 @@ SetSecurityLabel(const ObjectAddress *object, /* If we didn't find an old tuple, insert a new one */ if (newtup == NULL && label != NULL) { - newtup = heap_form_tuple(RelationGetDescr(pg_seclabel), - values, nulls); - CatalogTupleInsert(pg_seclabel, newtup); + newtup = heap_form_tuple(RelationGetDescr(pg_seclabel), values, nulls); + CatalogTupleInsert(pg_seclabel, newtup, NULL); } /* Update indexes, if necessary */ @@ -481,6 +475,7 @@ SetSecurityLabel(const ObjectAddress *object, heap_freetuple(newtup); table_close(pg_seclabel, RowExclusiveLock); + bms_free(updated); } /* diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 8d671b7a29d63..d936745d184da 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -136,8 +136,8 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq) TupleDesc tupDesc; Datum value[SEQ_COL_LASTCOL]; bool null[SEQ_COL_LASTCOL]; - Datum pgs_values[Natts_pg_sequence]; - bool pgs_nulls[Natts_pg_sequence]; + Datum pgs_values[Natts_pg_sequence] = {0}; + bool pgs_nulls[Natts_pg_sequence] = {false}; int i; /* @@ -232,17 +232,17 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq) memset(pgs_nulls, 0, sizeof(pgs_nulls)); - pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid); - pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid); - pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart); - pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement); - pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax); - pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin); - pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache); - pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle); + HeapTupleSetValue(pg_sequence, seqrelid, ObjectIdGetDatum(seqoid), pgs_values); + HeapTupleSetValue(pg_sequence, seqtypid, ObjectIdGetDatum(seqform.seqtypid), pgs_values); + HeapTupleSetValue(pg_sequence, seqstart, Int64GetDatumFast(seqform.seqstart), pgs_values); + HeapTupleSetValue(pg_sequence, seqincrement, Int64GetDatumFast(seqform.seqincrement), pgs_values); + HeapTupleSetValue(pg_sequence, seqmax, Int64GetDatumFast(seqform.seqmax), pgs_values); + HeapTupleSetValue(pg_sequence, seqmin, Int64GetDatumFast(seqform.seqmin), pgs_values); + HeapTupleSetValue(pg_sequence, seqcache, Int64GetDatumFast(seqform.seqcache), pgs_values); + HeapTupleSetValue(pg_sequence, seqcycle, BoolGetDatum(seqform.seqcycle), pgs_values); tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); table_close(rel, RowExclusiveLock); @@ -455,6 +455,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt) bool is_called; int64 last_value; HeapTuple newdatatuple; + Bitmapset *updated = NULL; /* Open and lock sequence, and check for ownership along the way. */ relid = RangeVarGetRelidExtended(stmt->sequence, @@ -536,8 +537,15 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt) if (owned_by) process_owned_by(seqrel, owned_by, stmt->for_identity); + /* + * Mark all sequence columns as potentially updated since init_params can + * modify any field + */ + HeapTupleUpdateSetAllColumnsUpdated(pg_sequence, updated); + /* update the pg_sequence tuple (we could skip this in some cases...) */ - CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple); + CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, relid, 0); diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 0cf0ea43f19b5..4addbed0754c6 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -71,8 +71,8 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights) Oid namespaceId; Oid stxowner = GetUserId(); HeapTuple htup; - Datum values[Natts_pg_statistic_ext]; - bool nulls[Natts_pg_statistic_ext]; + Datum values[Natts_pg_statistic_ext] = {0}; + bool nulls[Natts_pg_statistic_ext] = {false}; int2vector *stxkeys; List *stxexprs = NIL; Datum exprsDatum; @@ -525,22 +525,22 @@ CreateStatistics(CreateStatsStmt *stmt, bool check_rights) statoid = GetNewOidWithIndex(statrel, StatisticExtOidIndexId, Anum_pg_statistic_ext_oid); - values[Anum_pg_statistic_ext_oid - 1] = ObjectIdGetDatum(statoid); - values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname); - values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId); - values[Anum_pg_statistic_ext_stxowner - 1] = ObjectIdGetDatum(stxowner); - values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys); - nulls[Anum_pg_statistic_ext_stxstattarget - 1] = true; - values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind); - - values[Anum_pg_statistic_ext_stxexprs - 1] = exprsDatum; + HeapTupleSetValue(pg_statistic_ext, oid, ObjectIdGetDatum(statoid), values); + HeapTupleSetValue(pg_statistic_ext, stxrelid, ObjectIdGetDatum(relid), values); + HeapTupleSetValue(pg_statistic_ext, stxname, NameGetDatum(&stxname), values); + HeapTupleSetValue(pg_statistic_ext, stxnamespace, ObjectIdGetDatum(namespaceId), values); + HeapTupleSetValue(pg_statistic_ext, stxowner, ObjectIdGetDatum(stxowner), values); + HeapTupleSetValue(pg_statistic_ext, stxkeys, PointerGetDatum(stxkeys), values); + HeapTupleSetValueNull(pg_statistic_ext, stxstattarget, values, nulls); + HeapTupleSetValue(pg_statistic_ext, stxkind, PointerGetDatum(stxkind), values); + + HeapTupleSetValue(pg_statistic_ext, stxexprs, exprsDatum, values); if (exprsDatum == (Datum) 0) - nulls[Anum_pg_statistic_ext_stxexprs - 1] = true; + HeapTupleSetValueNull(pg_statistic_ext, stxexprs, values, nulls); /* insert it into pg_statistic_ext */ htup = heap_form_tuple(statrel->rd_att, values, nulls); - CatalogTupleInsert(statrel, htup); + CatalogTupleInsert(statrel, htup, NULL); heap_freetuple(htup); relation_close(statrel, RowExclusiveLock); @@ -636,9 +636,9 @@ AlterStatistics(AlterStatsStmt *stmt) Oid stxoid; HeapTuple oldtup; HeapTuple newtup; - Datum repl_val[Natts_pg_statistic_ext]; - bool repl_null[Natts_pg_statistic_ext]; - bool repl_repl[Natts_pg_statistic_ext]; + Datum values[Natts_pg_statistic_ext] = {0}; + bool nulls[Natts_pg_statistic_ext] = {false}; + Bitmapset *updated = NULL; ObjectAddress address; int newtarget = 0; bool newtarget_default; @@ -713,23 +713,16 @@ AlterStatistics(AlterStatsStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_STATISTIC_EXT, NameListToString(stmt->defnames)); - /* Build new tuple. */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* replace the stxstattarget column */ - repl_repl[Anum_pg_statistic_ext_stxstattarget - 1] = true; if (!newtarget_default) - repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int16GetDatum(newtarget); + HeapTupleUpdateValue(pg_statistic_ext, stxstattarget, Int16GetDatum(newtarget), values, nulls, updated); else - repl_null[Anum_pg_statistic_ext_stxstattarget - 1] = true; + HeapTupleUpdateValueNull(pg_statistic_ext, stxstattarget, values, nulls, updated); - newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + newtup = heap_update_tuple(oldtup, RelationGetDescr(rel), values, nulls, updated); /* Update system catalog. */ - CatalogTupleUpdate(rel, &newtup->t_self, newtup); + CatalogTupleUpdate(rel, &newtup->t_self, newtup, updated, NULL); InvokeObjectPostAlterHook(StatisticExtRelationId, stxoid, 0); @@ -740,6 +733,7 @@ AlterStatistics(AlterStatsStmt *stmt) * other fields, there is no need to update dependencies. */ + bms_free(updated); heap_freetuple(newtup); ReleaseSysCache(oldtup); diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 5930e8c581624..e368bfb35f747 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -589,8 +589,8 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, Relation rel; ObjectAddress myself; Oid subid; - bool nulls[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; Oid owner = GetUserId(); HeapTuple tup; char *conninfo; @@ -710,47 +710,35 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, subid = GetNewOidWithIndex(rel, SubscriptionObjectIndexId, Anum_pg_subscription_oid); - values[Anum_pg_subscription_oid - 1] = ObjectIdGetDatum(subid); - values[Anum_pg_subscription_subdbid - 1] = ObjectIdGetDatum(MyDatabaseId); - values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(InvalidXLogRecPtr); - values[Anum_pg_subscription_subname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->subname)); - values[Anum_pg_subscription_subowner - 1] = ObjectIdGetDatum(owner); - values[Anum_pg_subscription_subenabled - 1] = BoolGetDatum(opts.enabled); - values[Anum_pg_subscription_subbinary - 1] = BoolGetDatum(opts.binary); - values[Anum_pg_subscription_substream - 1] = CharGetDatum(opts.streaming); - values[Anum_pg_subscription_subtwophasestate - 1] = - CharGetDatum(opts.twophase ? - LOGICALREP_TWOPHASE_STATE_PENDING : - LOGICALREP_TWOPHASE_STATE_DISABLED); - values[Anum_pg_subscription_subdisableonerr - 1] = BoolGetDatum(opts.disableonerr); - values[Anum_pg_subscription_subpasswordrequired - 1] = BoolGetDatum(opts.passwordrequired); - values[Anum_pg_subscription_subrunasowner - 1] = BoolGetDatum(opts.runasowner); - values[Anum_pg_subscription_subfailover - 1] = BoolGetDatum(opts.failover); - values[Anum_pg_subscription_subretaindeadtuples - 1] = - BoolGetDatum(opts.retaindeadtuples); - values[Anum_pg_subscription_submaxretention - 1] = - Int32GetDatum(opts.maxretention); - values[Anum_pg_subscription_subretentionactive - 1] = - Int32GetDatum(opts.retaindeadtuples); - values[Anum_pg_subscription_subconninfo - 1] = - CStringGetTextDatum(conninfo); + HeapTupleSetValue(pg_subscription, oid, ObjectIdGetDatum(subid), values); + HeapTupleSetValue(pg_subscription, subdbid, ObjectIdGetDatum(MyDatabaseId), values); + HeapTupleSetValue(pg_subscription, subskiplsn, LSNGetDatum(InvalidXLogRecPtr), values); + HeapTupleSetValue(pg_subscription, subname, DirectFunctionCall1(namein, CStringGetDatum(stmt->subname)), values); + HeapTupleSetValue(pg_subscription, subowner, ObjectIdGetDatum(owner), values); + HeapTupleSetValue(pg_subscription, subenabled, BoolGetDatum(opts.enabled), values); + HeapTupleSetValue(pg_subscription, subbinary, BoolGetDatum(opts.binary), values); + HeapTupleSetValue(pg_subscription, substream, CharGetDatum(opts.streaming), values); + HeapTupleSetValue(pg_subscription, subtwophasestate, CharGetDatum(opts.twophase ? LOGICALREP_TWOPHASE_STATE_PENDING : LOGICALREP_TWOPHASE_STATE_DISABLED), values); + HeapTupleSetValue(pg_subscription, subdisableonerr, BoolGetDatum(opts.disableonerr), values); + HeapTupleSetValue(pg_subscription, subpasswordrequired, BoolGetDatum(opts.passwordrequired), values); + HeapTupleSetValue(pg_subscription, subrunasowner, BoolGetDatum(opts.runasowner), values); + HeapTupleSetValue(pg_subscription, subfailover, BoolGetDatum(opts.failover), values); + HeapTupleSetValue(pg_subscription, subretaindeadtuples, BoolGetDatum(opts.retaindeadtuples), values); + HeapTupleSetValue(pg_subscription, submaxretention, Int32GetDatum(opts.maxretention), values); + HeapTupleSetValue(pg_subscription, subretentionactive, Int32GetDatum(opts.retaindeadtuples), values); + HeapTupleSetValue(pg_subscription, subconninfo, CStringGetTextDatum(conninfo), values); if (opts.slot_name) - values[Anum_pg_subscription_subslotname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)); + HeapTupleSetValue(pg_subscription, subslotname, DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)), values); else - nulls[Anum_pg_subscription_subslotname - 1] = true; - values[Anum_pg_subscription_subsynccommit - 1] = - CStringGetTextDatum(opts.synchronous_commit); - values[Anum_pg_subscription_subpublications - 1] = - publicationListToArray(publications); - values[Anum_pg_subscription_suborigin - 1] = - CStringGetTextDatum(opts.origin); + HeapTupleSetValueNull(pg_subscription, subslotname, values, nulls); + HeapTupleSetValue(pg_subscription, subsynccommit, CStringGetTextDatum(opts.synchronous_commit), values); + HeapTupleSetValue(pg_subscription, subpublications, publicationListToArray(publications), values); + HeapTupleSetValue(pg_subscription, suborigin, CStringGetTextDatum(opts.origin), values); tup = heap_form_tuple(RelationGetDescr(rel), values, nulls); /* Insert tuple into catalog. */ - CatalogTupleInsert(rel, tup); + CatalogTupleInsert(rel, tup, NULL); heap_freetuple(tup); recordDependencyOnOwner(SubscriptionRelationId, subid, owner); @@ -1335,9 +1323,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, { Relation rel; ObjectAddress myself; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; HeapTuple tup; Oid subid; bool update_tuple = false; @@ -1352,6 +1339,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, Form_pg_subscription form; bits32 supported_opts; SubOpts opts = {0}; + Bitmapset *updated = NULL; rel = table_open(SubscriptionRelationId, RowExclusiveLock); @@ -1396,7 +1384,6 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, /* Form a new tuple. */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); switch (stmt->kind) { @@ -1431,41 +1418,27 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, "slot_name = NONE"))); if (opts.slot_name) - values[Anum_pg_subscription_subslotname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)); + HeapTupleUpdateValue(pg_subscription, subslotname, + DirectFunctionCall1(namein, CStringGetDatum(opts.slot_name)), values, nulls, updated); else - nulls[Anum_pg_subscription_subslotname - 1] = true; - replaces[Anum_pg_subscription_subslotname - 1] = true; + HeapTupleUpdateValueNull(pg_subscription, subslotname, values, nulls, updated); } if (opts.synchronous_commit) - { - values[Anum_pg_subscription_subsynccommit - 1] = - CStringGetTextDatum(opts.synchronous_commit); - replaces[Anum_pg_subscription_subsynccommit - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, subsynccommit, + CStringGetTextDatum(opts.synchronous_commit), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_BINARY)) - { - values[Anum_pg_subscription_subbinary - 1] = - BoolGetDatum(opts.binary); - replaces[Anum_pg_subscription_subbinary - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, subbinary, + BoolGetDatum(opts.binary), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_STREAMING)) - { - values[Anum_pg_subscription_substream - 1] = - CharGetDatum(opts.streaming); - replaces[Anum_pg_subscription_substream - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, substream, + CharGetDatum(opts.streaming), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_DISABLE_ON_ERR)) - { - values[Anum_pg_subscription_subdisableonerr - 1] - = BoolGetDatum(opts.disableonerr); - replaces[Anum_pg_subscription_subdisableonerr - 1] - = true; - } + HeapTupleUpdateValue(pg_subscription, subdisableonerr, + BoolGetDatum(opts.disableonerr), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_PASSWORD_REQUIRED)) { @@ -1476,18 +1449,13 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, errmsg("password_required=false is superuser-only"), errhint("Subscriptions with the password_required option set to false may only be created or modified by the superuser."))); - values[Anum_pg_subscription_subpasswordrequired - 1] - = BoolGetDatum(opts.passwordrequired); - replaces[Anum_pg_subscription_subpasswordrequired - 1] - = true; + HeapTupleUpdateValue(pg_subscription, subpasswordrequired, + BoolGetDatum(opts.passwordrequired), values, nulls, updated); } if (IsSet(opts.specified_opts, SUBOPT_RUN_AS_OWNER)) - { - values[Anum_pg_subscription_subrunasowner - 1] = - BoolGetDatum(opts.runasowner); - replaces[Anum_pg_subscription_subrunasowner - 1] = true; - } + HeapTupleUpdateValue(pg_subscription, subrunasowner, + BoolGetDatum(opts.runasowner), values, nulls, updated); if (IsSet(opts.specified_opts, SUBOPT_TWOPHASE_COMMIT)) { @@ -1546,11 +1514,10 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, errhint("Resolve these transactions and try again."))); /* Change system catalog accordingly */ - values[Anum_pg_subscription_subtwophasestate - 1] = - CharGetDatum(opts.twophase ? - LOGICALREP_TWOPHASE_STATE_PENDING : - LOGICALREP_TWOPHASE_STATE_DISABLED); - replaces[Anum_pg_subscription_subtwophasestate - 1] = true; + HeapTupleUpdateValue(pg_subscription, subtwophasestate, + CharGetDatum(opts.twophase ? + LOGICALREP_TWOPHASE_STATE_PENDING : + LOGICALREP_TWOPHASE_STATE_DISABLED), values, nulls, updated); } if (IsSet(opts.specified_opts, SUBOPT_FAILOVER)) @@ -1565,16 +1532,14 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, CheckAlterSubOption(sub, "failover", update_failover, isTopLevel); - values[Anum_pg_subscription_subfailover - 1] = - BoolGetDatum(opts.failover); - replaces[Anum_pg_subscription_subfailover - 1] = true; + HeapTupleUpdateValue(pg_subscription, subfailover, + BoolGetDatum(opts.failover), values, nulls, updated); } if (IsSet(opts.specified_opts, SUBOPT_RETAIN_DEAD_TUPLES)) { - values[Anum_pg_subscription_subretaindeadtuples - 1] = - BoolGetDatum(opts.retaindeadtuples); - replaces[Anum_pg_subscription_subretaindeadtuples - 1] = true; + HeapTupleUpdateValue(pg_subscription, subretaindeadtuples, + BoolGetDatum(opts.retaindeadtuples), values, nulls, updated); /* * Update the retention status only if there's a change in @@ -1592,9 +1557,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, */ if (opts.retaindeadtuples != sub->retaindeadtuples) { - values[Anum_pg_subscription_subretentionactive - 1] = - BoolGetDatum(opts.retaindeadtuples); - replaces[Anum_pg_subscription_subretentionactive - 1] = true; + HeapTupleUpdateValue(pg_subscription, subretentionactive, + BoolGetDatum(opts.retaindeadtuples), values, nulls, updated); retention_active = opts.retaindeadtuples; } @@ -1629,9 +1593,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, if (IsSet(opts.specified_opts, SUBOPT_MAX_RETENTION_DURATION)) { - values[Anum_pg_subscription_submaxretention - 1] = - Int32GetDatum(opts.maxretention); - replaces[Anum_pg_subscription_submaxretention - 1] = true; + HeapTupleUpdateValue(pg_subscription, submaxretention, + Int32GetDatum(opts.maxretention), values, nulls, updated); max_retention = opts.maxretention; } @@ -1650,9 +1613,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, if (IsSet(opts.specified_opts, SUBOPT_ORIGIN)) { - values[Anum_pg_subscription_suborigin - 1] = - CStringGetTextDatum(opts.origin); - replaces[Anum_pg_subscription_suborigin - 1] = true; + HeapTupleUpdateValue(pg_subscription, suborigin, + CStringGetTextDatum(opts.origin), values, nulls, updated); /* * Check if changes from different origins may be received @@ -1689,9 +1651,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, WARNING, sub->retaindeadtuples, sub->retentionactive, false); - values[Anum_pg_subscription_subenabled - 1] = - BoolGetDatum(opts.enabled); - replaces[Anum_pg_subscription_subenabled - 1] = true; + HeapTupleUpdateValue(pg_subscription, subenabled, + BoolGetDatum(opts.enabled), values, nulls, updated); if (opts.enabled) ApplyLauncherWakeupAtCommit(); @@ -1715,9 +1676,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, walrcv_check_conninfo(stmt->conninfo, sub->passwordrequired && !sub->ownersuperuser); - values[Anum_pg_subscription_subconninfo - 1] = - CStringGetTextDatum(stmt->conninfo); - replaces[Anum_pg_subscription_subconninfo - 1] = true; + HeapTupleUpdateValue(pg_subscription, subconninfo, + CStringGetTextDatum(stmt->conninfo), values, nulls, updated); update_tuple = true; /* @@ -1734,9 +1694,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, parse_subscription_options(pstate, stmt->options, supported_opts, &opts); - values[Anum_pg_subscription_subpublications - 1] = - publicationListToArray(stmt->publication); - replaces[Anum_pg_subscription_subpublications - 1] = true; + HeapTupleUpdateValue(pg_subscription, subpublications, + publicationListToArray(stmt->publication), values, nulls, updated); update_tuple = true; @@ -1782,9 +1741,8 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, supported_opts, &opts); publist = merge_publications(sub->publications, stmt->publication, isadd, stmt->subname); - values[Anum_pg_subscription_subpublications - 1] = - publicationListToArray(publist); - replaces[Anum_pg_subscription_subpublications - 1] = true; + HeapTupleUpdateValue(pg_subscription, subpublications, + publicationListToArray(publist), values, nulls, updated); update_tuple = true; @@ -1915,8 +1873,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, LSN_FORMAT_ARGS(remote_lsn)))); } - values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(opts.lsn); - replaces[Anum_pg_subscription_subskiplsn - 1] = true; + HeapTupleUpdateValue(pg_subscription, subskiplsn, LSNGetDatum(opts.lsn), values, nulls, updated); update_tuple = true; break; @@ -1930,10 +1887,9 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, /* Update the catalog if needed. */ if (update_tuple) { - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); heap_freetuple(tup); } @@ -2000,6 +1956,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, /* Wake up related replication workers to handle this change quickly. */ LogicalRepWorkersWakeupAtCommit(subid); + bms_free(updated); return myself; } @@ -2355,6 +2312,7 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) { Form_pg_subscription form; AclResult aclresult; + Bitmapset *updated = NULL; form = (Form_pg_subscription) GETSTRUCT(tup); @@ -2391,8 +2349,8 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) aclcheck_error(aclresult, OBJECT_DATABASE, get_database_name(MyDatabaseId)); - form->subowner = newOwnerId; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_subscription, subowner, newOwnerId, form, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* Update owner dependency reference */ changeDependencyOnOwner(SubscriptionRelationId, @@ -2405,6 +2363,7 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId) /* Wake up related background processes to handle this change quickly. */ ApplyLauncherWakeupAtCommit(); LogicalRepWorkersWakeupAtCommit(form->oid); + bms_free(updated); } /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 23ebaa3f23002..c7ecb2c10cce8 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3641,6 +3641,7 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass) Relation relationRelation; HeapTuple tuple; Form_pg_class classtuple; + Bitmapset *updated = NULL; Assert(CheckRelationOidLockedByMe(relationId, ShareUpdateExclusiveLock, false) || @@ -3658,8 +3659,8 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass) if (classtuple->relhassubclass != relhassubclass) { - classtuple->relhassubclass = relhassubclass; - CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relhassubclass, relhassubclass, classtuple, updated); + CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple, updated, NULL); } else { @@ -3668,6 +3669,7 @@ SetRelationHasSubclass(Oid relationId, bool relhassubclass) } heap_freetuple(tuple); + bms_free(updated); table_close(relationRelation, RowExclusiveLock); } @@ -3747,6 +3749,8 @@ SetRelationTableSpace(Relation rel, HeapTuple tuple; ItemPointerData otid; Form_pg_class rd_rel; + Bitmapset *updated = NULL; + Oid field = InvalidOid; Oid reloid = RelationGetRelid(rel); Assert(CheckRelationTableSpaceMove(rel, newTableSpaceId)); @@ -3761,11 +3765,16 @@ SetRelationTableSpace(Relation rel, rd_rel = (Form_pg_class) GETSTRUCT(tuple); /* Update the pg_class row. */ - rd_rel->reltablespace = (newTableSpaceId == MyDatabaseTableSpace) ? - InvalidOid : newTableSpaceId; + if (newTableSpaceId != MyDatabaseTableSpace) + field = newTableSpaceId; + + HeapTupleUpdateField(pg_class, reltablespace, field, rd_rel, updated); + if (RelFileNumberIsValid(newRelFilenumber)) - rd_rel->relfilenode = newRelFilenumber; - CatalogTupleUpdate(pg_class, &otid, tuple); + HeapTupleUpdateField(pg_class, relfilenode, newRelFilenumber, rd_rel, updated); + + CatalogTupleUpdate(pg_class, &otid, tuple, updated, NULL); + UnlockTuple(pg_class, &otid, InplaceUpdateTupleLock); /* @@ -3777,6 +3786,7 @@ SetRelationTableSpace(Relation rel, rd_rel->reltablespace); heap_freetuple(tuple); + bms_free(updated); table_close(pg_class, RowExclusiveLock); } @@ -3846,6 +3856,7 @@ renameatt_internal(Oid myrelid, HeapTuple atttup; Form_pg_attribute attform; AttrNumber attnum; + Bitmapset *updated = NULL; /* * Grab an exclusive lock on the target table, which we will NOT release @@ -3959,9 +3970,9 @@ renameatt_internal(Oid myrelid, (void) check_for_column_name_collision(targetrelation, newattname, false); /* apply the update */ - namestrcpy(&(attform->attname), newattname); - - CatalogTupleUpdate(attrelation, &atttup->t_self, atttup); + namestrcpy(&attform->attname, newattname); + CatalogTupleUpdate(attrelation, &atttup->t_self, atttup, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum); @@ -4267,6 +4278,7 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo HeapTuple reltup; Form_pg_class relform; Oid namespaceId; + Bitmapset *updated = NULL; /* * Grab a lock on the target relation, which we will NOT release until end @@ -4312,9 +4324,11 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo * Update pg_class tuple with new relname. (Scribbling on reltup is OK * because it's a copy...) */ - namestrcpy(&(relform->relname), newrelname); - CatalogTupleUpdate(relrelation, &otid, reltup); + namestrcpy(&relform->relname, newrelname); + CatalogTupleUpdate(relrelation, &otid, reltup, updated, NULL); + bms_free(updated); + UnlockTuple(relrelation, &otid, InplaceUpdateTupleLock); InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0, @@ -4357,6 +4371,7 @@ ResetRelRewrite(Oid myrelid) Relation relrelation; /* for RELATION relation */ HeapTuple reltup; Form_pg_class relform; + Bitmapset *updated = NULL; /* * Find relation's pg_class tuple. @@ -4368,13 +4383,11 @@ ResetRelRewrite(Oid myrelid) elog(ERROR, "cache lookup failed for relation %u", myrelid); relform = (Form_pg_class) GETSTRUCT(reltup); - /* - * Update pg_class tuple. - */ - relform->relrewrite = InvalidOid; - - CatalogTupleUpdate(relrelation, &reltup->t_self, reltup); + /* Update pg_class tuple */ + HeapTupleUpdateField(pg_class, relrewrite, InvalidOid, relform, updated); + CatalogTupleUpdate(relrelation, &reltup->t_self, reltup, updated, NULL); + bms_free(updated); heap_freetuple(reltup); table_close(relrelation, RowExclusiveLock); } @@ -7227,6 +7240,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, AlterTableCmd *childcmd; ObjectAddress address; TupleDesc tupdesc; + Bitmapset *updated = NULL; /* since this function recurses, it could be driven to stack overflow */ check_stack_depth(); @@ -7286,8 +7300,13 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); - CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple); + HeapTupleMarkColumnUpdated(pg_attribute, attinhcount, updated); + + CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple, updated, NULL); + + bms_free(updated); + updated = NULL; heap_freetuple(tuple); /* Inform the user about the merge */ @@ -7385,9 +7404,10 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, /* * Update pg_class tuple as appropriate */ - relform->relnatts = newattnum; - - CatalogTupleUpdate(pgclass, &reltup->t_self, reltup); + Assert(bms_is_empty(updated)); + HeapTupleUpdateField(pg_class, relnatts, newattnum, relform, updated); + CatalogTupleUpdate(pgclass, &reltup->t_self, reltup, updated, NULL); + bms_free(updated); heap_freetuple(reltup); @@ -7851,6 +7871,7 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, { Relation attr_rel; HeapTuple tuple; + Bitmapset *updated = NULL; attr_rel = table_open(AttributeRelationId, RowExclusiveLock); @@ -7864,8 +7885,9 @@ set_attnotnull(List **wqueue, Relation rel, AttrNumber attnum, attr = (Form_pg_attribute) GETSTRUCT(tuple); - attr->attnotnull = true; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attnotnull, true, attr, updated); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); /* * If the nullness isn't already proven by validated constraints, have @@ -7944,6 +7966,7 @@ ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName, { Form_pg_constraint conForm = (Form_pg_constraint) GETSTRUCT(tuple); bool changed = false; + Bitmapset *updated = NULL; /* * Don't let a NO INHERIT constraint be changed into inherit. @@ -7967,11 +7990,12 @@ ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName, ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated); changed = true; } else if (!conForm->conislocal) { - conForm->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, conForm, updated); changed = true; } else if (!conForm->convalidated) @@ -7990,7 +8014,8 @@ ATExecSetNotNull(List **wqueue, Relation rel, char *conName, char *colName, constr_rel = table_open(ConstraintRelationId, RowExclusiveLock); - CatalogTupleUpdate(constr_rel, &tuple->t_self, tuple); + CatalogTupleUpdate(constr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); ObjectAddressSet(address, ConstraintRelationId, conForm->oid); table_close(constr_rel, RowExclusiveLock); } @@ -8238,6 +8263,7 @@ ATExecAddIdentity(Relation rel, const char *colName, AttrNumber attnum; ObjectAddress address; ColumnDef *cdef = castNode(ColumnDef, def); + Bitmapset *updated = NULL; bool ispartitioned; ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); @@ -8318,8 +8344,9 @@ ATExecAddIdentity(Relation rel, const char *colName, errmsg("column \"%s\" of relation \"%s\" already has a default value", colName, RelationGetRelationName(rel)))); - attTup->attidentity = cdef->identity; - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attidentity, cdef->identity, attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8432,8 +8459,11 @@ ATExecSetIdentity(Relation rel, const char *colName, Node *def, if (generatedEl) { - attTup->attidentity = defGetInt32(generatedEl); - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_attribute, attidentity, defGetInt32(generatedEl), attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8488,6 +8518,7 @@ ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE Oid seqid; ObjectAddress seqaddress; bool ispartitioned; + Bitmapset *updated = NULL; ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); if (ispartitioned && !recurse) @@ -8536,8 +8567,9 @@ ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE } } - attTup->attidentity = '\0'; - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attidentity, '\0', attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8799,6 +8831,7 @@ ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMOD Relation attrelation; Oid attrdefoid; ObjectAddress address; + Bitmapset *updated = NULL; attrelation = table_open(AttributeRelationId, RowExclusiveLock); tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); @@ -8852,8 +8885,9 @@ ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMOD * Mark the column as no longer generated. (The atthasdef flag needs to * get cleared too, but RemoveAttrDefault will handle that.) */ - attTup->attgenerated = '\0'; - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attgenerated, '\0', attTup, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -8905,9 +8939,9 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa Form_pg_attribute attrtuple; AttrNumber attnum; ObjectAddress address; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; /* * We allow referencing columns by numbers only for indexes, since table @@ -9010,16 +9044,14 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa } /* Build new tuple. */ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (!newtarget_default) - repl_val[Anum_pg_attribute_attstattarget - 1] = Int16GetDatum(newtarget); + HeapTupleUpdateValue(pg_attribute, attstattarget, Int16GetDatum(newtarget), values, nulls, updated); else - repl_null[Anum_pg_attribute_attstattarget - 1] = true; - repl_repl[Anum_pg_attribute_attstattarget - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation), - repl_val, repl_null, repl_repl); - CatalogTupleUpdate(attrelation, &tuple->t_self, newtuple); + HeapTupleUpdateValueNull(pg_attribute, attstattarget, values, nulls, updated); + newtuple = heap_update_tuple(tuple, RelationGetDescr(attrelation), + values, nulls, updated); + CatalogTupleUpdate(attrelation, &tuple->t_self, newtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -9052,9 +9084,9 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, newOptions; bool isnull; ObjectAddress address; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; attrelation = table_open(AttributeRelationId, RowExclusiveLock); @@ -9084,18 +9116,17 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options, (void) attribute_reloptions(newOptions, true); /* Build new tuple. */ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_attribute_attoptions - 1] = newOptions; + HeapTupleUpdateValue(pg_attribute, attoptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_attribute_attoptions - 1] = true; - repl_repl[Anum_pg_attribute_attoptions - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation), - repl_val, repl_null, repl_repl); + HeapTupleUpdateValueNull(pg_attribute, attoptions, values, nulls, updated); + + newtuple = heap_update_tuple(tuple, RelationGetDescr(attrelation), + values, nulls, updated); /* Update system catalog. */ - CatalogTupleUpdate(attrelation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attrelation, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -9156,19 +9187,21 @@ SetIndexStorageProperties(Relation rel, Relation attrelation, if (HeapTupleIsValid(tuple)) { Form_pg_attribute attrtuple = (Form_pg_attribute) GETSTRUCT(tuple); + Bitmapset *updated = NULL; if (setstorage) - attrtuple->attstorage = newstorage; + HeapTupleUpdateField(pg_attribute, attstorage, newstorage, attrtuple, updated); if (setcompression) - attrtuple->attcompression = newcompression; + HeapTupleUpdateField(pg_attribute, attcompression, newcompression, attrtuple, updated); - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attrtuple->attnum); + bms_free(updated); heap_freetuple(tuple); } @@ -9189,6 +9222,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc Form_pg_attribute attrtuple; AttrNumber attnum; ObjectAddress address; + Bitmapset *updated = NULL; attrelation = table_open(AttributeRelationId, RowExclusiveLock); @@ -9208,9 +9242,9 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc errmsg("cannot alter system column \"%s\"", colName))); - attrtuple->attstorage = GetAttributeStorage(attrtuple->atttypid, strVal(newValue)); + HeapTupleUpdateField(pg_attribute, attstorage, GetAttributeStorage(attrtuple->atttypid, strVal(newValue)), attrtuple, updated); - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + CatalogTupleUpdate(attrelation, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -9225,6 +9259,7 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc false, 0, lockmode); + bms_free(updated); heap_freetuple(tuple); table_close(attrelation, RowExclusiveLock); @@ -9418,9 +9453,11 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, else { /* Child column must survive my deletion */ - childatt->attinhcount--; + Bitmapset *updated = NULL; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attinhcount, childatt->attinhcount - 1, childatt, updated); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); /* Make update visible */ CommandCounterIncrement(); @@ -9433,10 +9470,12 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, * we need to mark the inheritors' attributes as locally * defined rather than inherited. */ - childatt->attinhcount--; - childatt->attislocal = true; + Bitmapset *updated = NULL; - CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attinhcount, childatt->attinhcount - 1, childatt, updated); + HeapTupleUpdateField(pg_attribute, attislocal, true, childatt, updated); + CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); /* Make update visible */ CommandCounterIncrement(); @@ -12648,16 +12687,22 @@ ATExecAlterConstrInheritability(List **wqueue, ATAlterConstraint *cmdcon, { HeapTuple childtup; Form_pg_constraint childcon; + Bitmapset *updated = NULL; 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); + + HeapTupleUpdateField(pg_constraint, coninhcount, childcon->coninhcount - 1, childcon, updated); + HeapTupleUpdateField(pg_constraint, conislocal, true, childcon, updated); + + CatalogTupleUpdate(conrel, &childtup->t_self, childtup, updated, NULL); + + bms_free(updated); heap_freetuple(childtup); } else @@ -12702,6 +12747,7 @@ AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel, Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple); Form_pg_trigger copy_tg; HeapTuple tgCopyTuple; + Bitmapset *updated = NULL; /* * Remember OIDs of other relation(s) involved in FK constraint. @@ -12728,12 +12774,14 @@ AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel, 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); + HeapTupleUpdateField(pg_trigger, tgdeferrable, deferrable, copy_tg, updated); + HeapTupleUpdateField(pg_trigger, tginitdeferred, initdeferred, copy_tg, updated); + + CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple, updated, NULL); InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0); + bms_free(updated); heap_freetuple(tgCopyTuple); } @@ -12848,6 +12896,7 @@ AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, { HeapTuple copyTuple; Form_pg_constraint copy_con; + Bitmapset *updated = NULL; Assert(cmdcon->alterEnforceability || cmdcon->alterDeferrability || cmdcon->alterInheritability); @@ -12857,7 +12906,7 @@ AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, if (cmdcon->alterEnforceability) { - copy_con->conenforced = cmdcon->is_enforced; + HeapTupleUpdateField(pg_constraint, conenforced, cmdcon->is_enforced, copy_con, updated); /* * NB: The convalidated status is irrelevant when the constraint is @@ -12866,22 +12915,26 @@ AlterConstrUpdateConstraintEntry(ATAlterConstraint *cmdcon, Relation conrel, * 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; + HeapTupleUpdateField(pg_constraint, convalidated, cmdcon->is_enforced, copy_con, updated); } + if (cmdcon->alterDeferrability) { - copy_con->condeferrable = cmdcon->deferrable; - copy_con->condeferred = cmdcon->initdeferred; + HeapTupleUpdateField(pg_constraint, condeferrable, cmdcon->deferrable, copy_con, updated); + HeapTupleUpdateField(pg_constraint, condeferred, cmdcon->initdeferred, copy_con, updated); } + if (cmdcon->alterInheritability) - copy_con->connoinherit = cmdcon->noinherit; + HeapTupleUpdateField(pg_constraint, connoinherit, cmdcon->noinherit, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); InvokeObjectPostAlterHook(ConstraintRelationId, copy_con->oid, 0); /* Make new constraint flags visible to others */ CacheInvalidateRelcacheByRelid(copy_con->conrelid); + bms_free(updated); heap_freetuple(copyTuple); } @@ -12994,6 +13047,7 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel, AlteredTableInfo *tab; HeapTuple copyTuple; Form_pg_constraint copy_con; + Bitmapset *updated = NULL; con = (Form_pg_constraint) GETSTRUCT(contuple); Assert(con->contype == CONSTRAINT_FOREIGN); @@ -13090,11 +13144,14 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation fkrel, */ copyTuple = heap_copytuple(contuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + bms_free(updated); heap_freetuple(copyTuple); } @@ -13120,6 +13177,7 @@ QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel, NewConstraint *newcon; Datum val; char *conbin; + Bitmapset *updated = NULL; con = (Form_pg_constraint) GETSTRUCT(contuple); Assert(con->contype == CONSTRAINT_CHECK); @@ -13193,11 +13251,14 @@ QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel, */ copyTuple = heap_copytuple(contuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + bms_free(updated); heap_freetuple(copyTuple); } @@ -13220,6 +13281,7 @@ QueueNNConstraintValidation(List **wqueue, Relation conrel, Relation rel, List *children = NIL; AttrNumber attnum; char *colname; + Bitmapset *updated = NULL; con = (Form_pg_constraint) GETSTRUCT(contuple); Assert(con->contype == CONSTRAINT_NOTNULL); @@ -13296,11 +13358,14 @@ QueueNNConstraintValidation(List **wqueue, Relation conrel, Relation rel, */ copyTuple = heap_copytuple(contuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); + bms_free(updated); heap_freetuple(copyTuple); } @@ -14175,8 +14240,11 @@ dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior beha /* All good -- reset attnotnull if needed */ if (attForm->attnotnull) { - attForm->attnotnull = false; - CatalogTupleUpdate(attrel, &atttup->t_self, atttup); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_attribute, attnotnull, false, attForm, updated); + CatalogTupleUpdate(attrel, &atttup->t_self, atttup, updated, NULL); + bms_free(updated); } table_close(attrel, RowExclusiveLock); @@ -14309,11 +14377,16 @@ dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior beha else { /* Child constraint must survive my deletion */ - childcon->coninhcount--; - CatalogTupleUpdate(conrel, &tuple->t_self, tuple); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_constraint, coninhcount, childcon->coninhcount - 1, childcon, updated); + + CatalogTupleUpdate(conrel, &tuple->t_self, tuple, updated, NULL); /* Make update visible */ CommandCounterIncrement(); + + bms_free(updated); } } else @@ -14324,14 +14397,19 @@ dropconstraint_internal(Relation rel, HeapTuple constraintTup, DropBehavior beha * mark the inheritors' constraints as locally defined rather than * inherited. */ - childcon->coninhcount--; + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_constraint, coninhcount, childcon->coninhcount - 1, childcon, updated); + if (childcon->coninhcount == 0) - childcon->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, childcon, updated); - CatalogTupleUpdate(conrel, &tuple->t_self, tuple); + CatalogTupleUpdate(conrel, &tuple->t_self, tuple, updated, NULL); /* Make update visible */ CommandCounterIncrement(); + + bms_free(updated); } heap_freetuple(tuple); @@ -14737,6 +14815,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, SysScanDesc scan; HeapTuple depTup; ObjectAddress address; + Bitmapset *updated = NULL; /* * Clear all the missing values if we're rewriting the table, since this @@ -14913,9 +14992,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, int one = 1; bool isNull; - Datum valuesAtt[Natts_pg_attribute] = {0}; - bool nullsAtt[Natts_pg_attribute] = {0}; - bool replacesAtt[Natts_pg_attribute] = {0}; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; HeapTuple newTup; missingval = array_get_element(missingval, @@ -14933,35 +15011,36 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, tform->typbyval, tform->typalign)); - valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval; - replacesAtt[Anum_pg_attribute_attmissingval - 1] = true; - nullsAtt[Anum_pg_attribute_attmissingval - 1] = false; + HeapTupleUpdateValue(pg_attribute, attmissingval, missingval, values, nulls, updated); - newTup = heap_modify_tuple(heapTup, RelationGetDescr(attrelation), - valuesAtt, nullsAtt, replacesAtt); + newTup = heap_update_tuple(heapTup, RelationGetDescr(attrelation), + values, nulls, updated); heap_freetuple(heapTup); + bms_free(updated); + updated = NULL; + heapTup = newTup; attTup = (Form_pg_attribute) GETSTRUCT(heapTup); } } - attTup->atttypid = targettype; - attTup->atttypmod = targettypmod; - attTup->attcollation = targetcollid; + HeapTupleUpdateField(pg_attribute, atttypid, targettype, attTup, updated); + HeapTupleUpdateField(pg_attribute, atttypmod, targettypmod, attTup, updated); + HeapTupleUpdateField(pg_attribute, attcollation, targetcollid, attTup, updated); if (list_length(typeName->arrayBounds) > PG_INT16_MAX) ereport(ERROR, errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many array dimensions")); - attTup->attndims = list_length(typeName->arrayBounds); - attTup->attlen = tform->typlen; - attTup->attbyval = tform->typbyval; - attTup->attalign = tform->typalign; - attTup->attstorage = tform->typstorage; - attTup->attcompression = InvalidCompressionMethod; + HeapTupleUpdateField(pg_attribute, attndims, list_length(typeName->arrayBounds), attTup, updated); + HeapTupleUpdateField(pg_attribute, attlen, tform->typlen, attTup, updated); + HeapTupleUpdateField(pg_attribute, attbyval, tform->typbyval, attTup, updated); + HeapTupleUpdateField(pg_attribute, attalign, tform->typalign, attTup, updated); + HeapTupleUpdateField(pg_attribute, attstorage, tform->typstorage, attTup, updated); + HeapTupleUpdateField(pg_attribute, attcompression, InvalidCompressionMethod, attTup, updated); ReleaseSysCache(typeTuple); - CatalogTupleUpdate(attrelation, &heapTup->t_self, heapTup); + CatalogTupleUpdate(attrelation, &heapTup->t_self, heapTup, updated, NULL); table_close(attrelation, RowExclusiveLock); @@ -15021,6 +15100,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, RelationGetRelid(rel), attnum); /* Cleanup */ + bms_free(updated); heap_freetuple(heapTup); return address; @@ -15956,9 +16036,9 @@ ATExecAlterColumnGenericOptions(Relation rel, HeapTuple tuple; HeapTuple newtuple; bool isnull; - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Datum datum; Form_pg_foreign_table fttableform; Form_pg_attribute atttableform; @@ -16000,11 +16080,6 @@ ATExecAlterColumnGenericOptions(Relation rel, errmsg("cannot alter system column \"%s\"", colName))); - /* Initialize buffers for new tuple values */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* Extract the current options */ datum = SysCacheGetAttr(ATTNAME, tuple, @@ -16020,18 +16095,15 @@ ATExecAlterColumnGenericOptions(Relation rel, fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_attribute_attfdwoptions - 1] = datum; + HeapTupleUpdateValue(pg_attribute, attfdwoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_attribute_attfdwoptions - 1] = true; - - repl_repl[Anum_pg_attribute_attfdwoptions - 1] = true; + HeapTupleUpdateValueNull(pg_attribute, attfdwoptions, values, nulls, updated); /* Everything looks good - update the tuple */ + newtuple = heap_update_tuple(tuple, RelationGetDescr(attrel), + values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel), - repl_val, repl_null, repl_repl); - - CatalogTupleUpdate(attrel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attrel, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -16043,6 +16115,7 @@ ATExecAlterColumnGenericOptions(Relation rel, table_close(attrel, RowExclusiveLock); + bms_free(updated); heap_freetuple(newtuple); return address; @@ -16169,13 +16242,13 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock */ if (tuple_class->relowner != newOwnerId) { - Datum repl_val[Natts_pg_class]; - bool repl_null[Natts_pg_class]; - bool repl_repl[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; Acl *newAcl; Datum aclDatum; bool isNull; HeapTuple newtuple; + Bitmapset *updated = NULL; /* skip permission checks when recursing to index or toast table */ if (!recursing) @@ -16203,11 +16276,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock } } - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_class_relowner - 1] = true; - repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_class, relowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); /* * Determine the modified ACL for the new owner. This is only @@ -16220,14 +16289,14 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock { newAcl = aclnewowner(DatumGetAclP(aclDatum), tuple_class->relowner, newOwnerId); - repl_repl[Anum_pg_class_relacl - 1] = true; - repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_class, relacl, PointerGetDatum(newAcl), values, nulls, updated); } - newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tuple, RelationGetDescr(class_rel), values, nulls, updated); - CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); heap_freetuple(newtuple); /* @@ -16319,9 +16388,9 @@ change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId) while (HeapTupleIsValid(attributeTuple = systable_getnext(scan))) { Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple); - Datum repl_val[Natts_pg_attribute]; - bool repl_null[Natts_pg_attribute]; - bool repl_repl[Natts_pg_attribute]; + Datum values[Natts_pg_attribute] = {0}; + bool nulls[Natts_pg_attribute] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -16339,20 +16408,17 @@ change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId) if (isNull) continue; - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - newAcl = aclnewowner(DatumGetAclP(aclDatum), oldOwnerId, newOwnerId); - repl_repl[Anum_pg_attribute_attacl - 1] = true; - repl_val[Anum_pg_attribute_attacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_attribute, attacl, PointerGetDatum(newAcl), values, nulls, updated); - newtuple = heap_modify_tuple(attributeTuple, + newtuple = heap_update_tuple(attributeTuple, RelationGetDescr(attRelation), - repl_val, repl_null, repl_repl); + values, nulls, updated); - CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple); + CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); heap_freetuple(newtuple); } systable_endscan(scan); @@ -16521,6 +16587,7 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) HeapTuple tuple; Form_pg_class rd_rel; Oid reloid = RelationGetRelid(rel); + Bitmapset *updated = NULL; /* * Shouldn't be called on relations having storage; these are processed in @@ -16538,17 +16605,18 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) /* Update the pg_class row. */ oldAccessMethodId = rd_rel->relam; - rd_rel->relam = newAccessMethodId; + HeapTupleUpdateField(pg_class, relam, newAccessMethodId, rd_rel, updated); /* Leave if no update required */ if (rd_rel->relam == oldAccessMethodId) { + bms_free(updated); heap_freetuple(tuple); table_close(pg_class, RowExclusiveLock); return; } - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + CatalogTupleUpdate(pg_class, &tuple->t_self, tuple, updated, NULL); /* * Update the dependency on the new access method. No dependency is added @@ -16596,6 +16664,7 @@ ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); + bms_free(updated); heap_freetuple(tuple); table_close(pg_class, RowExclusiveLock); } @@ -16643,9 +16712,9 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, HeapTuple newtuple; Datum datum; Datum newOptions; - Datum repl_val[Natts_pg_class]; - bool repl_null[Natts_pg_class]; - bool repl_repl[Natts_pg_class]; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; const char *const validnsps[] = HEAP_RELOPT_NAMESPACES; if (defList == NIL && operation != AT_ReplaceRelOptions) @@ -16747,25 +16816,23 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, * All we need do here is update the pg_class row; the new options will be * propagated into relcaches during post-commit cache inval. */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_class_reloptions - 1] = newOptions; + HeapTupleUpdateValue(pg_class, reloptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_class_reloptions - 1] = true; + HeapTupleUpdateValueNull(pg_class, reloptions, values, nulls, updated); - repl_repl[Anum_pg_class_reloptions - 1] = true; + newtuple = heap_update_tuple(tuple, RelationGetDescr(pgclass), + values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass), - repl_val, repl_null, repl_repl); + CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple, updated, NULL); - CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple); UnlockTuple(pgclass, &tuple->t_self, InplaceUpdateTupleLock); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); + bms_free(updated); + updated = NULL; heap_freetuple(newtuple); ReleaseSysCache(tuple); @@ -16807,26 +16874,25 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation, (void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); + memset(values, 0, sizeof(values)); + memset(nulls, false, sizeof(nulls)); + Assert(bms_is_empty(updated)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_class_reloptions - 1] = newOptions; + HeapTupleUpdateValue(pg_class, reloptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_class_reloptions - 1] = true; - - repl_repl[Anum_pg_class_reloptions - 1] = true; + HeapTupleUpdateValueNull(pg_class, reloptions, values, nulls, updated); - newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass), - repl_val, repl_null, repl_repl); + newtuple = heap_update_tuple(tuple, RelationGetDescr(pgclass), + values, nulls, updated); - CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple); + CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHookArg(RelationRelationId, RelationGetRelid(toastrel), 0, InvalidOid, true); + bms_free(updated); heap_freetuple(newtuple); ReleaseSysCache(tuple); @@ -17498,6 +17564,7 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart for (AttrNumber parent_attno = 1; parent_attno <= parent_desc->natts; parent_attno++) { Form_pg_attribute parent_att = TupleDescAttr(parent_desc, parent_attno - 1); + Bitmapset *updated = NULL; char *parent_attname = NameStr(parent_att->attname); HeapTuple tuple; @@ -17582,6 +17649,8 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleMarkColumnUpdated(pg_attribute, attinhcount, updated); + /* * In case of partitions, we must enforce that value of attislocal * is same in all partitions. (Note: there are only inherited @@ -17590,10 +17659,12 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispart if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { Assert(child_att->attinhcount == 1); - child_att->attislocal = false; + HeapTupleUpdateField(pg_attribute, attislocal, false, child_att, updated); } - CatalogTupleUpdate(attrrel, &tuple->t_self, tuple); + CatalogTupleUpdate(attrrel, &tuple->t_self, tuple, updated, NULL); + + bms_free(updated); heap_freetuple(tuple); } else @@ -17656,6 +17727,7 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) HeapTuple child_tuple; AttrNumber parent_attno; bool found = false; + Bitmapset *updated = NULL; if (parent_con->contype != CONSTRAINT_CHECK && parent_con->contype != CONSTRAINT_NOTNULL) @@ -17764,6 +17836,8 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("too many inheritance parents")); + HeapTupleMarkColumnUpdated(pg_constraint, coninhcount, updated); + /* * In case of partitions, an inherited constraint must be * inherited only once since it cannot have multiple parents and @@ -17772,10 +17846,12 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel) if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) { Assert(child_con->coninhcount == 1); - child_con->conislocal = false; + HeapTupleUpdateField(pg_constraint, conislocal, false, child_con, updated); } - CatalogTupleUpdate(constraintrel, &child_copy->t_self, child_copy); + CatalogTupleUpdate(constraintrel, &child_copy->t_self, child_copy, updated, NULL); + + bms_free(updated); heap_freetuple(child_copy); found = true; @@ -17879,6 +17955,7 @@ MarkInheritDetached(Relation child_rel, Relation parent_rel) while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan))) { Form_pg_inherits inhForm; + Bitmapset *updated = NULL; inhForm = (Form_pg_inherits) GETSTRUCT(inheritsTuple); if (inhForm->inhdetachpending) @@ -17893,14 +17970,18 @@ MarkInheritDetached(Relation child_rel, Relation parent_rel) if (inhForm->inhrelid == RelationGetRelid(child_rel)) { HeapTuple newtup; + Form_pg_inherits classForm; newtup = heap_copytuple(inheritsTuple); - ((Form_pg_inherits) GETSTRUCT(newtup))->inhdetachpending = true; + classForm = (Form_pg_inherits) GETSTRUCT(newtup); + + HeapTupleUpdateField(pg_inherits, inhdetachpending, true, classForm, updated); + + CatalogTupleUpdate(catalogRelation, &inheritsTuple->t_self, newtup, updated, NULL); - CatalogTupleUpdate(catalogRelation, - &inheritsTuple->t_self, - newtup); found = true; + + bms_free(updated); heap_freetuple(newtup); /* keep looking, to ensure we catch others pending detach */ } @@ -17985,6 +18066,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) while (HeapTupleIsValid(attributeTuple = systable_getnext(scan))) { Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple); + Bitmapset *updated = NULL; /* Ignore if dropped or not inherited */ if (att->attisdropped) @@ -17999,11 +18081,14 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) HeapTuple copyTuple = heap_copytuple(attributeTuple); Form_pg_attribute copy_att = (Form_pg_attribute) GETSTRUCT(copyTuple); - copy_att->attinhcount--; + HeapTupleUpdateField(pg_attribute, attinhcount, copy_att->attinhcount - 1, copy_att, updated); + if (copy_att->attinhcount == 0) - copy_att->attislocal = true; + HeapTupleUpdateField(pg_attribute, attislocal, true, copy_att, updated); - CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple); + CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple, updated, NULL); + + bms_free(updated); heap_freetuple(copyTuple); } } @@ -18065,6 +18150,7 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) { Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple); bool match = false; + Bitmapset *updated = NULL; /* * Match CHECK constraints by name, not-null constraints by column @@ -18110,11 +18196,14 @@ RemoveInheritance(Relation child_rel, Relation parent_rel, bool expect_detached) elog(ERROR, "relation %u has non-inherited constraint \"%s\"", RelationGetRelid(child_rel), NameStr(copy_con->conname)); - copy_con->coninhcount--; + HeapTupleUpdateField(pg_constraint, coninhcount, copy_con->coninhcount - 1, copy_con, updated); + if (copy_con->coninhcount == 0) - copy_con->conislocal = true; + HeapTupleUpdateField(pg_constraint, conislocal, true, copy_con, updated); - CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple); + CatalogTupleUpdate(catalogRelation, ©Tuple->t_self, copyTuple, updated, NULL); + + bms_free(updated); heap_freetuple(copyTuple); } } @@ -18220,6 +18309,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) ObjectAddress tableobj, typeobj; HeapTuple classtuple; + Bitmapset *updated = NULL; /* Validate the type. */ typetuple = typenameType(NULL, ofTypename, NULL); @@ -18325,11 +18415,14 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) classtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(classtuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid; - CatalogTupleUpdate(relationRelation, &classtuple->t_self, classtuple); + + HeapTupleUpdateField(pg_class, reloftype, typeid, (Form_pg_class) GETSTRUCT(classtuple), updated); + + CatalogTupleUpdate(relationRelation, &classtuple->t_self, classtuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, relid, 0); + bms_free(updated); heap_freetuple(classtuple); table_close(relationRelation, RowExclusiveLock); @@ -18350,6 +18443,7 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode) Oid relid = RelationGetRelid(rel); Relation relationRelation; HeapTuple tuple; + Bitmapset *updated = NULL; if (!OidIsValid(rel->rd_rel->reloftype)) ereport(ERROR, @@ -18370,11 +18464,14 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode) tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid; - CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple); + + HeapTupleUpdateField(pg_class, reloftype, InvalidOid, (Form_pg_class) GETSTRUCT(tuple), updated); + + CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, relid, 0); + bms_free(updated); heap_freetuple(tuple); table_close(relationRelation, RowExclusiveLock); } @@ -18412,8 +18509,11 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, pg_class_form = (Form_pg_class) GETSTRUCT(pg_class_tuple); if (pg_class_form->relreplident != ri_type) { - pg_class_form->relreplident = ri_type; - CatalogTupleUpdate(pg_class, &pg_class_tuple->t_self, pg_class_tuple); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_class, relreplident, ri_type, pg_class_form, updated); + CatalogTupleUpdate(pg_class, &pg_class_tuple->t_self, pg_class_tuple, updated, NULL); + bms_free(updated); } table_close(pg_class, RowExclusiveLock); heap_freetuple(pg_class_tuple); @@ -18426,6 +18526,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, { Oid thisIndexOid = lfirst_oid(index); bool dirty = false; + Bitmapset *updated = NULL; pg_index_tuple = SearchSysCacheCopy1(INDEXRELID, ObjectIdGetDatum(thisIndexOid)); @@ -18439,7 +18540,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, if (!pg_index_form->indisreplident) { dirty = true; - pg_index_form->indisreplident = true; + HeapTupleUpdateField(pg_index, indisreplident, true, pg_index_form, updated); } } else @@ -18448,13 +18549,13 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, if (pg_index_form->indisreplident) { dirty = true; - pg_index_form->indisreplident = false; + HeapTupleUpdateField(pg_index, indisreplident, false, pg_index_form, updated); } } if (dirty) { - CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple); + CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple, updated, NULL); InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0, InvalidOid, is_internal); @@ -18467,6 +18568,7 @@ relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid, */ CacheInvalidateRelcache(rel); } + bms_free(updated); heap_freetuple(pg_index_tuple); } @@ -18596,6 +18698,7 @@ ATExecSetRowSecurity(Relation rel, bool rls) Relation pg_class; Oid relid; HeapTuple tuple; + Bitmapset *updated = NULL; relid = RelationGetRelid(rel); @@ -18607,13 +18710,14 @@ ATExecSetRowSecurity(Relation rel, bool rls) if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = rls; - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relrowsecurity, rls, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pg_class, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); table_close(pg_class, RowExclusiveLock); + bms_free(updated); heap_freetuple(tuple); } @@ -18626,6 +18730,7 @@ ATExecForceNoForceRowSecurity(Relation rel, bool force_rls) Relation pg_class; Oid relid; HeapTuple tuple; + Bitmapset *updated = NULL; relid = RelationGetRelid(rel); @@ -18636,13 +18741,14 @@ ATExecForceNoForceRowSecurity(Relation rel, bool force_rls) if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for relation %u", relid); - ((Form_pg_class) GETSTRUCT(tuple))->relforcerowsecurity = force_rls; - CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relforcerowsecurity, force_rls, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pg_class, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); table_close(pg_class, RowExclusiveLock); + bms_free(updated); heap_freetuple(tuple); } @@ -18657,9 +18763,9 @@ ATExecGenericOptions(Relation rel, List *options) ForeignDataWrapper *fdw; HeapTuple tuple; bool isnull; - Datum repl_val[Natts_pg_foreign_table]; - bool repl_null[Natts_pg_foreign_table]; - bool repl_repl[Natts_pg_foreign_table]; + Datum values[Natts_pg_foreign_table] = {0}; + bool nulls[Natts_pg_foreign_table] = {false}; + Bitmapset *updated = NULL; Datum datum; Form_pg_foreign_table tableform; @@ -18679,10 +18785,6 @@ ATExecGenericOptions(Relation rel, List *options) server = GetForeignServer(tableform->ftserver); fdw = GetForeignDataWrapper(server->fdwid); - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - /* Extract the current options */ datum = SysCacheGetAttr(FOREIGNTABLEREL, tuple, @@ -18698,18 +18800,16 @@ ATExecGenericOptions(Relation rel, List *options) fdw->fdwvalidator); if (DatumGetPointer(datum) != NULL) - repl_val[Anum_pg_foreign_table_ftoptions - 1] = datum; + HeapTupleUpdateValue(pg_foreign_table, ftoptions, datum, values, nulls, updated); else - repl_null[Anum_pg_foreign_table_ftoptions - 1] = true; - - repl_repl[Anum_pg_foreign_table_ftoptions - 1] = true; + HeapTupleUpdateValueNull(pg_foreign_table, ftoptions, values, nulls, updated); /* Everything looks good - update the tuple */ - tuple = heap_modify_tuple(tuple, RelationGetDescr(ftrel), - repl_val, repl_null, repl_repl); + tuple = heap_update_tuple(tuple, RelationGetDescr(ftrel), + values, nulls, updated); - CatalogTupleUpdate(ftrel, &tuple->t_self, tuple); + CatalogTupleUpdate(ftrel, &tuple->t_self, tuple, updated, NULL); /* * Invalidate relcache so that all sessions will refresh any cached plans @@ -18722,6 +18822,7 @@ ATExecGenericOptions(Relation rel, List *options) table_close(ftrel, RowExclusiveLock); + bms_free(updated); heap_freetuple(tuple); } @@ -18743,6 +18844,7 @@ ATExecSetCompression(Relation rel, char *compression; char cmethod; ObjectAddress address; + Bitmapset *updated = NULL; compression = strVal(newValue); @@ -18771,8 +18873,8 @@ ATExecSetCompression(Relation rel, cmethod = GetAttributeCompression(atttableform->atttypid, compression); /* update pg_attribute entry */ - atttableform->attcompression = cmethod; - CatalogTupleUpdate(attrel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_attribute, attcompression, cmethod, atttableform, updated); + CatalogTupleUpdate(attrel, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), @@ -18787,6 +18889,7 @@ ATExecSetCompression(Relation rel, true, cmethod, lockmode); + bms_free(updated); heap_freetuple(tuple); table_close(attrel, RowExclusiveLock); @@ -19050,6 +19153,7 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Form_pg_class classForm; ObjectAddress thisobj; bool already_done = false; + Bitmapset *updated = NULL; /* no rel lock for relkind=c so use LOCKTAG_TUPLE */ classTup = SearchSysCacheLockedCopy1(RELOID, ObjectIdGetDatum(relOid)); @@ -19083,9 +19187,10 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid, get_namespace_name(newNspOid)))); /* classTup is a copy, so OK to scribble on */ - classForm->relnamespace = newNspOid; + HeapTupleUpdateField(pg_class, relnamespace, newNspOid, classForm, updated); - CatalogTupleUpdate(classRel, &otid, classTup); + CatalogTupleUpdate(classRel, &otid, classTup, updated, NULL); + bms_free(updated); UnlockTuple(classRel, &otid, InplaceUpdateTupleLock); @@ -21077,9 +21182,9 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, List *fks; ListCell *cell; List *indexes; - Datum new_val[Natts_pg_class]; - bool new_null[Natts_pg_class], - new_repl[Natts_pg_class]; + Datum new_val[Natts_pg_class] = {0}; + bool new_null[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; HeapTuple tuple, newtuple; Relation trigrel = NULL; @@ -21329,17 +21434,13 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, Assert(((Form_pg_class) GETSTRUCT(tuple))->relispartition); /* Clear relpartbound and reset relispartition */ - memset(new_val, 0, sizeof(new_val)); - memset(new_null, false, sizeof(new_null)); - memset(new_repl, false, sizeof(new_repl)); - new_val[Anum_pg_class_relpartbound - 1] = (Datum) 0; - new_null[Anum_pg_class_relpartbound - 1] = true; - new_repl[Anum_pg_class_relpartbound - 1] = true; - newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel), - new_val, new_null, new_repl); - - ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = false; - CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple); + HeapTupleUpdateValueNull(pg_class, relpartbound, new_val, new_null, updated); + newtuple = heap_update_tuple(tuple, RelationGetDescr(classRel), + new_val, new_null, updated); + + HeapTupleUpdateField(pg_class, relispartition, false, (Form_pg_class) GETSTRUCT(newtuple), updated); + CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple, updated, NULL); + bms_free(updated); heap_freetuple(newtuple); table_close(classRel, RowExclusiveLock); @@ -21759,6 +21860,7 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) int tuples = 0; HeapTuple inhTup; bool updated = false; + Bitmapset *updated_cols = NULL; Assert(partedIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX); @@ -21811,10 +21913,11 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) RelationGetRelid(partedIdx)); indexForm = (Form_pg_index) GETSTRUCT(indTup); - indexForm->indisvalid = true; + HeapTupleUpdateField(pg_index, indisvalid, true, indexForm, updated_cols); updated = true; - CatalogTupleUpdate(idxRel, &indTup->t_self, indTup); + CatalogTupleUpdate(idxRel, &indTup->t_self, indTup, updated_cols, NULL); + bms_free(updated_cols); table_close(idxRel, RowExclusiveLock); heap_freetuple(indTup); diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index df31eace47ac9..5b89be5983c40 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -208,8 +208,8 @@ Oid CreateTableSpace(CreateTableSpaceStmt *stmt) { Relation rel; - Datum values[Natts_pg_tablespace]; - bool nulls[Natts_pg_tablespace] = {0}; + Datum values[Natts_pg_tablespace] = {0}; + bool nulls[Natts_pg_tablespace] = {false}; HeapTuple tuple; Oid tablespaceoid; char *location; @@ -325,12 +325,10 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) else tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId, Anum_pg_tablespace_oid); - values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid); - values[Anum_pg_tablespace_spcname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename)); - values[Anum_pg_tablespace_spcowner - 1] = - ObjectIdGetDatum(ownerId); - nulls[Anum_pg_tablespace_spcacl - 1] = true; + HeapTupleSetValue(pg_tablespace, oid, ObjectIdGetDatum(tablespaceoid), values); + HeapTupleSetValue(pg_tablespace, spcname, DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename)), values); + HeapTupleSetValue(pg_tablespace, spcowner, ObjectIdGetDatum(ownerId), values); + HeapTupleSetValueNull(pg_tablespace, spcacl, values, nulls); /* Generate new proposed spcoptions (text array) */ newOptions = transformRelOptions((Datum) 0, @@ -338,13 +336,13 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) NULL, NULL, false, false); (void) tablespace_reloptions(newOptions, true); if (newOptions != (Datum) 0) - values[Anum_pg_tablespace_spcoptions - 1] = newOptions; + HeapTupleSetValue(pg_tablespace, spcoptions, newOptions, values); else - nulls[Anum_pg_tablespace_spcoptions - 1] = true; + HeapTupleSetValueNull(pg_tablespace, spcoptions, values, nulls); tuple = heap_form_tuple(rel->rd_att, values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); heap_freetuple(tuple); @@ -937,6 +935,7 @@ RenameTableSpace(const char *oldname, const char *newname) HeapTuple newtuple; Form_pg_tablespace newform; ObjectAddress address; + Bitmapset *updated = NULL; /* Search pg_tablespace */ rel = table_open(TableSpaceRelationId, RowExclusiveLock); @@ -996,14 +995,15 @@ RenameTableSpace(const char *oldname, const char *newname) /* OK, update the entry */ namestrcpy(&(newform->spcname), newname); - - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + HeapTupleMarkColumnUpdated(pg_tablespace, spcname, updated); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHook(TableSpaceRelationId, tspId, 0); ObjectAddressSet(address, TableSpaceRelationId, tspId); table_close(rel, NoLock); + bms_free(updated); return address; } @@ -1021,10 +1021,10 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) Oid tablespaceoid; Datum datum; Datum newOptions; - Datum repl_val[Natts_pg_tablespace]; + Datum values[Natts_pg_tablespace] = {0}; + bool nulls[Natts_pg_tablespace] = {false}; + Bitmapset *updated = NULL; bool isnull; - bool repl_null[Natts_pg_tablespace]; - bool repl_repl[Natts_pg_tablespace]; HeapTuple newtuple; /* Search pg_tablespace */ @@ -1058,26 +1058,25 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) (void) tablespace_reloptions(newOptions, true); /* Build new tuple. */ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); if (newOptions != (Datum) 0) - repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions; + HeapTupleUpdateValue(pg_tablespace, spcoptions, newOptions, values, nulls, updated); else - repl_null[Anum_pg_tablespace_spcoptions - 1] = true; - repl_repl[Anum_pg_tablespace_spcoptions - 1] = true; - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, - repl_null, repl_repl); + HeapTupleUpdateValueNull(pg_tablespace, spcoptions, values, nulls, updated); + newtuple = heap_update_tuple(tup, RelationGetDescr(rel), values, + nulls, updated); /* Update system catalog. */ - CatalogTupleUpdate(rel, &newtuple->t_self, newtuple); + CatalogTupleUpdate(rel, &newtuple->t_self, newtuple, updated, NULL); InvokeObjectPostAlterHook(TableSpaceRelationId, tablespaceoid, 0); heap_freetuple(newtuple); + bms_free(updated); /* Conclude heap scan. */ table_endscan(scandesc); table_close(rel, NoLock); + bms_free(updated); return tablespaceoid; } diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 579ac8d76ae73..1cd1f3fc478bc 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -186,8 +186,9 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, int2vector *tgattr; List *whenRtable; char *qual; - Datum values[Natts_pg_trigger]; - bool nulls[Natts_pg_trigger]; + Datum values[Natts_pg_trigger] = {0}; + bool nulls[Natts_pg_trigger] = {false}; + Bitmapset *updated = NULL; Relation rel; AclResult aclresult; Relation tgrel; @@ -751,8 +752,7 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, if (!trigger_exists) { /* Generate the OID for the new trigger. */ - trigoid = GetNewOidWithIndex(tgrel, TriggerOidIndexId, - Anum_pg_trigger_oid); + trigoid = GetNewOidWithIndex(tgrel, TriggerOidIndexId, Anum_pg_trigger_oid); } else { @@ -862,22 +862,19 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, /* * Build the new pg_trigger tuple. */ - memset(nulls, false, sizeof(nulls)); - - values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid); - values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); - values[Anum_pg_trigger_tgparentid - 1] = ObjectIdGetDatum(parentTriggerOid); - values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein, - CStringGetDatum(trigname)); - values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid); - values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype); - values[Anum_pg_trigger_tgenabled - 1] = CharGetDatum(trigger_fires_when); - values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal); - values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid); - values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid); - values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid); - values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable); - values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred); + HeapTupleUpdateValue(pg_trigger, oid, ObjectIdGetDatum(trigoid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgrelid, ObjectIdGetDatum(RelationGetRelid(rel)), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgparentid, ObjectIdGetDatum(parentTriggerOid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgname, DirectFunctionCall1(namein, CStringGetDatum(trigname)), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgfoid, ObjectIdGetDatum(funcoid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgtype, Int16GetDatum(tgtype), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgenabled, CharGetDatum(trigger_fires_when), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgisinternal, BoolGetDatum(isInternal), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgconstrrelid, ObjectIdGetDatum(constrrelid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgconstrindid, ObjectIdGetDatum(indexOid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgconstraint, ObjectIdGetDatum(constraintOid), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgdeferrable, BoolGetDatum(stmt->deferrable), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tginitdeferred, BoolGetDatum(stmt->initdeferred), values, nulls, updated); if (stmt->args) { @@ -912,15 +909,13 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, } strcpy(d, "\\000"); } - values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs); - values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain, - CStringGetDatum(args)); + HeapTupleUpdateValue(pg_trigger, tgnargs, Int16GetDatum(nargs), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgargs, DirectFunctionCall1(byteain, CStringGetDatum(args)), values, nulls, updated); } else { - values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0); - values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain, - CStringGetDatum("")); + HeapTupleUpdateValue(pg_trigger, tgnargs, Int16GetDatum(0), values, nulls, updated); + HeapTupleUpdateValue(pg_trigger, tgargs, DirectFunctionCall1(byteain, CStringGetDatum("")), values, nulls, updated); } /* build column number array if it's a column-specific trigger */ @@ -961,24 +956,23 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, } } tgattr = buildint2vector(columns, ncolumns); - values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr); + HeapTupleUpdateValue(pg_trigger, tgattr, PointerGetDatum(tgattr), values, nulls, updated); /* set tgqual if trigger has WHEN clause */ if (qual) - values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual); + HeapTupleUpdateValue(pg_trigger, tgqual, CStringGetTextDatum(qual), values, nulls, updated); else - nulls[Anum_pg_trigger_tgqual - 1] = true; + HeapTupleUpdateValueNull(pg_trigger, tgqual, values, nulls, updated); if (oldtablename) - values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein, - CStringGetDatum(oldtablename)); + HeapTupleUpdateValue(pg_trigger, tgoldtable, DirectFunctionCall1(namein, CStringGetDatum(oldtablename)), values, nulls, updated); else - nulls[Anum_pg_trigger_tgoldtable - 1] = true; + HeapTupleUpdateValueNull(pg_trigger, tgoldtable, values, nulls, updated); + if (newtablename) - values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein, - CStringGetDatum(newtablename)); + HeapTupleUpdateValue(pg_trigger, tgnewtable, DirectFunctionCall1(namein, CStringGetDatum(newtablename)), values, nulls, updated); else - nulls[Anum_pg_trigger_tgnewtable - 1] = true; + HeapTupleUpdateValueNull(pg_trigger, tgnewtable, values, nulls, updated); /* * Insert or replace tuple in pg_trigger. @@ -986,27 +980,29 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, if (!trigger_exists) { tuple = heap_form_tuple(tgrel->rd_att, values, nulls); - CatalogTupleInsert(tgrel, tuple); + CatalogTupleInsert(tgrel, tuple, NULL); } else { HeapTuple newtup; newtup = heap_form_tuple(tgrel->rd_att, values, nulls); - CatalogTupleUpdate(tgrel, &tuple->t_self, newtup); + CatalogTupleUpdate(tgrel, &tuple->t_self, newtup, updated, NULL); heap_freetuple(newtup); } heap_freetuple(tuple); /* free either original or new tuple */ table_close(tgrel, RowExclusiveLock); + bms_free(updated); + updated = NULL; - pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1])); - pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1])); - pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgname, values))); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgargs, values))); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgattr, values))); if (oldtablename) - pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgoldtable, values))); if (newtablename) - pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1])); + pfree(DatumGetPointer(HeapTupleValue(pg_trigger, tgnewtable, values))); /* * Update relation's pg_class entry; if necessary; and if not, send an SI @@ -1020,9 +1016,9 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, RelationGetRelid(rel)); if (!((Form_pg_class) GETSTRUCT(tuple))->relhastriggers) { - ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true; - - CatalogTupleUpdate(pgrel, &tuple->t_self, tuple); + HeapTupleUpdateField(pg_class, relhastriggers, true, (Form_pg_class) GETSTRUCT(tuple), updated); + CatalogTupleUpdate(pgrel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); CommandCounterIncrement(); } @@ -1229,6 +1225,7 @@ TriggerSetParentTrigger(Relation trigRel, newtup; ObjectAddress depender; ObjectAddress referenced; + Bitmapset *updated = NULL; /* * Find the trigger to delete. @@ -1253,9 +1250,9 @@ TriggerSetParentTrigger(Relation trigRel, elog(ERROR, "trigger %u already has a parent trigger", childTrigId); - trigForm->tgparentid = parentTrigId; + HeapTupleUpdateField(pg_trigger, tgparentid, parentTrigId, trigForm, updated); - CatalogTupleUpdate(trigRel, &tuple->t_self, newtup); + CatalogTupleUpdate(trigRel, &tuple->t_self, newtup, updated, NULL); ObjectAddressSet(depender, TriggerRelationId, childTrigId); @@ -1267,9 +1264,9 @@ TriggerSetParentTrigger(Relation trigRel, } else { - trigForm->tgparentid = InvalidOid; + HeapTupleUpdateField(pg_trigger, tgparentid, InvalidOid, trigForm, updated); - CatalogTupleUpdate(trigRel, &tuple->t_self, newtup); + CatalogTupleUpdate(trigRel, &tuple->t_self, newtup, updated, NULL); deleteDependencyRecordsForClass(TriggerRelationId, childTrigId, TriggerRelationId, @@ -1281,6 +1278,7 @@ TriggerSetParentTrigger(Relation trigRel, heap_freetuple(newtup); systable_endscan(tgscan); + bms_free(updated); } @@ -1586,6 +1584,7 @@ renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, Form_pg_trigger tgform; ScanKeyData key[2]; SysScanDesc tgscan; + Bitmapset *updated = NULL; /* If the trigger already has the new name, nothing to do. */ tgform = (Form_pg_trigger) GETSTRUCT(trigtup); @@ -1633,7 +1632,7 @@ renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, namestrcpy(&tgform->tgname, newname); - CatalogTupleUpdate(tgrel, &tuple->t_self, tuple); + CatalogTupleUpdate(tgrel, &tuple->t_self, tuple, updated, NULL); InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0); @@ -1643,6 +1642,7 @@ renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, * (Ideally this should happen automatically...) */ CacheInvalidateRelcache(targetrel); + bms_free(updated); } /* @@ -1784,11 +1784,12 @@ EnableDisableTrigger(Relation rel, const char *tgname, Oid tgparent, /* need to change this one ... make a copy to scribble on */ HeapTuple newtup = heap_copytuple(tuple); Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup); + Bitmapset *updated = NULL; - newtrig->tgenabled = fires_when; - - CatalogTupleUpdate(tgrel, &newtup->t_self, newtup); + HeapTupleUpdateField(pg_trigger, tgenabled, fires_when, newtrig, updated); + CatalogTupleUpdate(tgrel, &newtup->t_self, newtup, updated, NULL); + bms_free(updated); heap_freetuple(newtup); changed = true; diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index dc7df736fb826..eebf05c2d7961 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -187,8 +187,8 @@ DefineTSParser(List *names, List *parameters) ListCell *pl; Relation prsRel; HeapTuple tup; - Datum values[Natts_pg_ts_parser]; - bool nulls[Natts_pg_ts_parser]; + Datum values[Natts_pg_ts_parser] = {0}; + bool nulls[Natts_pg_ts_parser] = {false}; NameData pname; Oid prsOid; Oid namespaceoid; @@ -210,10 +210,10 @@ DefineTSParser(List *names, List *parameters) prsOid = GetNewOidWithIndex(prsRel, TSParserOidIndexId, Anum_pg_ts_parser_oid); - values[Anum_pg_ts_parser_oid - 1] = ObjectIdGetDatum(prsOid); + HeapTupleSetValue(pg_ts_parser, oid, ObjectIdGetDatum(prsOid), values); namestrcpy(&pname, prsname); - values[Anum_pg_ts_parser_prsname - 1] = NameGetDatum(&pname); - values[Anum_pg_ts_parser_prsnamespace - 1] = ObjectIdGetDatum(namespaceoid); + HeapTupleSetValue(pg_ts_parser, prsname, NameGetDatum(&pname), values); + HeapTupleSetValue(pg_ts_parser, prsnamespace, ObjectIdGetDatum(namespaceoid), values); /* * loop over the definition list and extract the information we need. @@ -224,28 +224,23 @@ DefineTSParser(List *names, List *parameters) if (strcmp(defel->defname, "start") == 0) { - values[Anum_pg_ts_parser_prsstart - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prsstart); + HeapTupleSetValue(pg_ts_parser, prsstart, get_ts_parser_func(defel, Anum_pg_ts_parser_prsstart), values); } else if (strcmp(defel->defname, "gettoken") == 0) { - values[Anum_pg_ts_parser_prstoken - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prstoken); + HeapTupleSetValue(pg_ts_parser, prstoken, get_ts_parser_func(defel, Anum_pg_ts_parser_prstoken), values); } else if (strcmp(defel->defname, "end") == 0) { - values[Anum_pg_ts_parser_prsend - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prsend); + HeapTupleSetValue(pg_ts_parser, prsend, get_ts_parser_func(defel, Anum_pg_ts_parser_prsend), values); } else if (strcmp(defel->defname, "headline") == 0) { - values[Anum_pg_ts_parser_prsheadline - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prsheadline); + HeapTupleSetValue(pg_ts_parser, prsheadline, get_ts_parser_func(defel, Anum_pg_ts_parser_prsheadline), values); } else if (strcmp(defel->defname, "lextypes") == 0) { - values[Anum_pg_ts_parser_prslextype - 1] = - get_ts_parser_func(defel, Anum_pg_ts_parser_prslextype); + HeapTupleSetValue(pg_ts_parser, prslextype, get_ts_parser_func(defel, Anum_pg_ts_parser_prslextype), values); } else ereport(ERROR, @@ -257,22 +252,22 @@ DefineTSParser(List *names, List *parameters) /* * Validation */ - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsstart - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prsstart, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser start method is required"))); - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prstoken - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prstoken, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser gettoken method is required"))); - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prsend - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prsend, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser end method is required"))); - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_parser_prslextype - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_parser, prslextype, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search parser lextypes method is required"))); @@ -282,7 +277,7 @@ DefineTSParser(List *names, List *parameters) */ tup = heap_form_tuple(prsRel->rd_att, values, nulls); - CatalogTupleInsert(prsRel, tup); + CatalogTupleInsert(prsRel, tup, NULL); address = makeParserDependencies(tup); @@ -399,8 +394,8 @@ DefineTSDictionary(List *names, List *parameters) ListCell *pl; Relation dictRel; HeapTuple tup; - Datum values[Natts_pg_ts_dict]; - bool nulls[Natts_pg_ts_dict]; + Datum values[Natts_pg_ts_dict] = {0}; + bool nulls[Natts_pg_ts_dict] = {false}; NameData dname; Oid templId = InvalidOid; List *dictoptions = NIL; @@ -458,21 +453,20 @@ DefineTSDictionary(List *names, List *parameters) dictOid = GetNewOidWithIndex(dictRel, TSDictionaryOidIndexId, Anum_pg_ts_dict_oid); - values[Anum_pg_ts_dict_oid - 1] = ObjectIdGetDatum(dictOid); + HeapTupleSetValue(pg_ts_dict, oid, ObjectIdGetDatum(dictOid), values); namestrcpy(&dname, dictname); - values[Anum_pg_ts_dict_dictname - 1] = NameGetDatum(&dname); - values[Anum_pg_ts_dict_dictnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_ts_dict_dictowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_ts_dict_dicttemplate - 1] = ObjectIdGetDatum(templId); + HeapTupleSetValue(pg_ts_dict, dictname, NameGetDatum(&dname), values); + HeapTupleSetValue(pg_ts_dict, dictnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_ts_dict, dictowner, ObjectIdGetDatum(GetUserId()), values); + HeapTupleSetValue(pg_ts_dict, dicttemplate, ObjectIdGetDatum(templId), values); if (dictoptions) - values[Anum_pg_ts_dict_dictinitoption - 1] = - PointerGetDatum(serialize_deflist(dictoptions)); + HeapTupleSetValue(pg_ts_dict, dictinitoption, PointerGetDatum(serialize_deflist(dictoptions)), values); else - nulls[Anum_pg_ts_dict_dictinitoption - 1] = true; + HeapTupleSetValueNull(pg_ts_dict, dictinitoption, values, nulls); tup = heap_form_tuple(dictRel->rd_att, values, nulls); - CatalogTupleInsert(dictRel, tup); + CatalogTupleInsert(dictRel, tup, NULL); address = makeDictionaryDependencies(tup); @@ -500,9 +494,9 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) List *dictoptions; Datum opt; bool isnull; - Datum repl_val[Natts_pg_ts_dict]; - bool repl_null[Natts_pg_ts_dict]; - bool repl_repl[Natts_pg_ts_dict]; + Datum values[Natts_pg_ts_dict] = {0}; + bool nulls[Natts_pg_ts_dict] = {false}; + Bitmapset *updated = NULL; ObjectAddress address; dictId = get_ts_dict_oid(stmt->dictname, false); @@ -564,21 +558,15 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) /* * Looks good, update */ - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - if (dictoptions) - repl_val[Anum_pg_ts_dict_dictinitoption - 1] = - PointerGetDatum(serialize_deflist(dictoptions)); + HeapTupleUpdateValue(pg_ts_dict, dictinitoption, PointerGetDatum(serialize_deflist(dictoptions)), values, nulls, updated); else - repl_null[Anum_pg_ts_dict_dictinitoption - 1] = true; - repl_repl[Anum_pg_ts_dict_dictinitoption - 1] = true; + HeapTupleUpdateValueNull(pg_ts_dict, dictinitoption, values, nulls, updated); - newtup = heap_modify_tuple(tup, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); + newtup = heap_update_tuple(tup, RelationGetDescr(rel), + values, nulls, updated); - CatalogTupleUpdate(rel, &newtup->t_self, newtup); + CatalogTupleUpdate(rel, &newtup->t_self, newtup, updated, NULL); InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0); @@ -594,6 +582,7 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt) ReleaseSysCache(tup); table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -692,8 +681,8 @@ DefineTSTemplate(List *names, List *parameters) ListCell *pl; Relation tmplRel; HeapTuple tup; - Datum values[Natts_pg_ts_template]; - bool nulls[Natts_pg_ts_template]; + Datum values[Natts_pg_ts_template] = {0}; + bool nulls[Natts_pg_ts_template] = {false}; NameData dname; int i; Oid tmplOid; @@ -719,10 +708,10 @@ DefineTSTemplate(List *names, List *parameters) tmplOid = GetNewOidWithIndex(tmplRel, TSTemplateOidIndexId, Anum_pg_ts_dict_oid); - values[Anum_pg_ts_template_oid - 1] = ObjectIdGetDatum(tmplOid); + HeapTupleSetValue(pg_ts_template, oid, ObjectIdGetDatum(tmplOid), values); namestrcpy(&dname, tmplname); - values[Anum_pg_ts_template_tmplname - 1] = NameGetDatum(&dname); - values[Anum_pg_ts_template_tmplnamespace - 1] = ObjectIdGetDatum(namespaceoid); + HeapTupleSetValue(pg_ts_template, tmplname, NameGetDatum(&dname), values); + HeapTupleSetValue(pg_ts_template, tmplnamespace, ObjectIdGetDatum(namespaceoid), values); /* * loop over the definition list and extract the information we need. @@ -733,15 +722,11 @@ DefineTSTemplate(List *names, List *parameters) if (strcmp(defel->defname, "init") == 0) { - values[Anum_pg_ts_template_tmplinit - 1] = - get_ts_template_func(defel, Anum_pg_ts_template_tmplinit); - nulls[Anum_pg_ts_template_tmplinit - 1] = false; + HeapTupleSetValue(pg_ts_template, tmplinit, get_ts_template_func(defel, Anum_pg_ts_template_tmplinit), values); } else if (strcmp(defel->defname, "lexize") == 0) { - values[Anum_pg_ts_template_tmpllexize - 1] = - get_ts_template_func(defel, Anum_pg_ts_template_tmpllexize); - nulls[Anum_pg_ts_template_tmpllexize - 1] = false; + HeapTupleSetValue(pg_ts_template, tmpllexize, get_ts_template_func(defel, Anum_pg_ts_template_tmpllexize), values); } else ereport(ERROR, @@ -753,7 +738,7 @@ DefineTSTemplate(List *names, List *parameters) /* * Validation */ - if (!OidIsValid(DatumGetObjectId(values[Anum_pg_ts_template_tmpllexize - 1]))) + if (!OidIsValid(DatumGetObjectId(HeapTupleValue(pg_ts_template, tmpllexize, values)))) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("text search template lexize method is required"))); @@ -763,7 +748,7 @@ DefineTSTemplate(List *names, List *parameters) */ tup = heap_form_tuple(tmplRel->rd_att, values, nulls); - CatalogTupleInsert(tmplRel, tup); + CatalogTupleInsert(tmplRel, tup, NULL); address = makeTSTemplateDependencies(tup); @@ -901,8 +886,8 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) Relation cfgRel; Relation mapRel = NULL; HeapTuple tup; - Datum values[Natts_pg_ts_config]; - bool nulls[Natts_pg_ts_config]; + Datum values[Natts_pg_ts_config] = {0}; + bool nulls[Natts_pg_ts_config] = {false}; AclResult aclresult; Oid namespaceoid; char *cfgname; @@ -991,16 +976,16 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) cfgOid = GetNewOidWithIndex(cfgRel, TSConfigOidIndexId, Anum_pg_ts_config_oid); - values[Anum_pg_ts_config_oid - 1] = ObjectIdGetDatum(cfgOid); + HeapTupleSetValue(pg_ts_config, oid, ObjectIdGetDatum(cfgOid), values); namestrcpy(&cname, cfgname); - values[Anum_pg_ts_config_cfgname - 1] = NameGetDatum(&cname); - values[Anum_pg_ts_config_cfgnamespace - 1] = ObjectIdGetDatum(namespaceoid); - values[Anum_pg_ts_config_cfgowner - 1] = ObjectIdGetDatum(GetUserId()); - values[Anum_pg_ts_config_cfgparser - 1] = ObjectIdGetDatum(prsOid); + HeapTupleSetValue(pg_ts_config, cfgname, NameGetDatum(&cname), values); + HeapTupleSetValue(pg_ts_config, cfgnamespace, ObjectIdGetDatum(namespaceoid), values); + HeapTupleSetValue(pg_ts_config, cfgowner, ObjectIdGetDatum(GetUserId()), values); + HeapTupleSetValue(pg_ts_config, cfgparser, ObjectIdGetDatum(prsOid), values); tup = heap_form_tuple(cfgRel->rd_att, values, nulls); - CatalogTupleInsert(cfgRel, tup); + CatalogTupleInsert(cfgRel, tup, NULL); if (OidIsValid(sourceOid)) { @@ -1058,10 +1043,10 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) memset(slot[slot_stored_count]->tts_isnull, false, slot[slot_stored_count]->tts_tupleDescriptor->natts * sizeof(bool)); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgOid); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(cfgmap->maptokentype); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapseqno - 1] = Int32GetDatum(cfgmap->mapseqno); - slot[slot_stored_count]->tts_values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(cfgmap->mapdict); + HeapTupleSetValue(pg_ts_config_map, mapcfg, ObjectIdGetDatum(cfgOid), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_ts_config_map, maptokentype, Int32GetDatum(cfgmap->maptokentype), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapseqno, Int32GetDatum(cfgmap->mapseqno), slot[slot_stored_count]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapdict, ObjectIdGetDatum(cfgmap->mapdict), slot[slot_stored_count]->tts_values); ExecStoreVirtualTuple(slot[slot_stored_count]); slot_stored_count++; @@ -1069,16 +1054,16 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied) /* If slots are full, insert a batch of tuples */ if (slot_stored_count == max_slots) { - CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(mapRel, slot, slot_stored_count, + indstate); slot_stored_count = 0; } } /* Insert any tuples left in the buffer */ if (slot_stored_count > 0) - CatalogTuplesMultiInsertWithInfo(mapRel, slot, slot_stored_count, - indstate); + CatalogTuplesMultiInsert(mapRel, slot, slot_stored_count, + indstate); for (int i = 0; i < slot_init_count; i++) ExecDropSingleTupleTableSlot(slot[i]); @@ -1402,22 +1387,18 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, */ if (cfgmap->mapdict == dictOld) { - Datum repl_val[Natts_pg_ts_config_map]; - bool repl_null[Natts_pg_ts_config_map]; - bool repl_repl[Natts_pg_ts_config_map]; + Datum values[Natts_pg_ts_config_map] = {0}; + bool nulls[Natts_pg_ts_config_map] = {false}; + Bitmapset *updated = NULL; HeapTuple newtup; - memset(repl_val, 0, sizeof(repl_val)); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_val[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictNew); - repl_repl[Anum_pg_ts_config_map_mapdict - 1] = true; + HeapTupleUpdateValue(pg_ts_config_map, mapdict, ObjectIdGetDatum(dictNew), values, nulls, updated); - newtup = heap_modify_tuple(maptup, + newtup = heap_update_tuple(maptup, RelationGetDescr(relMap), - repl_val, repl_null, repl_repl); - CatalogTupleUpdateWithInfo(relMap, &newtup->t_self, newtup, indstate); + values, nulls, updated); + CatalogTupleUpdate(relMap, &newtup->t_self, newtup, updated, indstate); + bms_free(updated); } } @@ -1451,10 +1432,10 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, memset(slot[slotCount]->tts_isnull, false, slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool)); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgId); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_maptokentype - 1] = Int32GetDatum(ts->num); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapseqno - 1] = Int32GetDatum(j + 1); - slot[slotCount]->tts_values[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(dictIds[j]); + HeapTupleSetValue(pg_ts_config_map, mapcfg, ObjectIdGetDatum(cfgId), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_ts_config_map, maptokentype, Int32GetDatum(ts->num), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapseqno, Int32GetDatum(j + 1), slot[slotCount]->tts_values); + HeapTupleSetValue(pg_ts_config_map, mapdict, ObjectIdGetDatum(dictIds[j]), slot[slotCount]->tts_values); ExecStoreVirtualTuple(slot[slotCount]); slotCount++; @@ -1462,8 +1443,8 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, /* If slots are full, insert a batch of tuples */ if (slotCount == nslots) { - CatalogTuplesMultiInsertWithInfo(relMap, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(relMap, slot, slotCount, + indstate); slotCount = 0; } } @@ -1471,8 +1452,8 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt, /* Insert any tuples left in the buffer */ if (slotCount > 0) - CatalogTuplesMultiInsertWithInfo(relMap, slot, slotCount, - indstate); + CatalogTuplesMultiInsert(relMap, slot, slotCount, + indstate); for (i = 0; i < nslots; i++) ExecDropSingleTupleTableSlot(slot[i]); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 5979580139fc6..d7fa069a17ade 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -2620,9 +2620,9 @@ AlterDomainDefault(List *names, Node *defaultRaw) Relation rel; char *defaultValue; Node *defaultExpr = NULL; /* NULL if no default specified */ - Datum new_record[Natts_pg_type] = {0}; - bool new_record_nulls[Natts_pg_type] = {0}; - bool new_record_repl[Natts_pg_type] = {0}; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; HeapTuple newtuple; Form_pg_type typTup; ObjectAddress address; @@ -2670,10 +2670,8 @@ AlterDomainDefault(List *names, Node *defaultRaw) { /* Default is NULL, drop it */ defaultExpr = NULL; - new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true; - new_record_repl[Anum_pg_type_typdefaultbin - 1] = true; - new_record_nulls[Anum_pg_type_typdefault - 1] = true; - new_record_repl[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated); + HeapTupleUpdateValueNull(pg_type, typdefault, values, nulls, updated); } else { @@ -2688,27 +2686,21 @@ AlterDomainDefault(List *names, Node *defaultRaw) /* * Form an updated tuple with the new default and write it back. */ - new_record[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(nodeToString(defaultExpr)); - - new_record_repl[Anum_pg_type_typdefaultbin - 1] = true; - new_record[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultValue); - new_record_repl[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValue(pg_type, typdefaultbin, CStringGetTextDatum(nodeToString(defaultExpr)), values, nulls, updated); + HeapTupleUpdateValue(pg_type, typdefault, CStringGetTextDatum(defaultValue), values, nulls, updated); } } else { /* ALTER ... DROP DEFAULT */ - new_record_nulls[Anum_pg_type_typdefaultbin - 1] = true; - new_record_repl[Anum_pg_type_typdefaultbin - 1] = true; - new_record_nulls[Anum_pg_type_typdefault - 1] = true; - new_record_repl[Anum_pg_type_typdefault - 1] = true; + HeapTupleUpdateValueNull(pg_type, typdefaultbin, values, nulls, updated); + HeapTupleUpdateValueNull(pg_type, typdefault, values, nulls, updated); } - newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), - new_record, new_record_nulls, - new_record_repl); + newtuple = heap_update_tuple(tup, RelationGetDescr(rel), + values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, newtuple); + CatalogTupleUpdate(rel, &tup->t_self, newtuple, updated, NULL); /* Rebuild dependencies */ GenerateTypeDependencies(newtuple, @@ -2728,6 +2720,7 @@ AlterDomainDefault(List *names, Node *defaultRaw) /* Clean up */ table_close(rel, RowExclusiveLock); heap_freetuple(newtuple); + bms_free(updated); return address; } @@ -2748,6 +2741,7 @@ AlterDomainNotNull(List *names, bool notNull) HeapTuple tup; Form_pg_type typTup; ObjectAddress address = InvalidObjectAddress; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -2803,9 +2797,9 @@ AlterDomainNotNull(List *names, bool notNull) * Okay to update pg_type row. We can scribble on typTup because it's a * copy. */ - typTup->typnotnull = notNull; + HeapTupleUpdateField(pg_type, typnotnull, notNull, typTup, updated); - CatalogTupleUpdate(typrel, &tup->t_self, tup); + CatalogTupleUpdate(typrel, &tup->t_self, tup, updated, NULL); InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0); @@ -2814,6 +2808,7 @@ AlterDomainNotNull(List *names, bool notNull) /* Clean up */ heap_freetuple(tup); table_close(typrel, RowExclusiveLock); + bms_free(updated); return address; } @@ -2839,6 +2834,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, HeapTuple contup; bool found = false; ObjectAddress address; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -2882,8 +2878,8 @@ AlterDomainDropConstraint(List *names, const char *constrName, if (construct->contype == CONSTRAINT_NOTNULL) { - ((Form_pg_type) GETSTRUCT(tup))->typnotnull = false; - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_type, typnotnull, false, (Form_pg_type) GETSTRUCT(tup), updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); } conobj.classId = ConstraintRelationId; @@ -2922,6 +2918,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, /* Clean up */ table_close(rel, RowExclusiveLock); + bms_free(updated); return address; } @@ -2943,6 +2940,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint, Constraint *constr; char *ccbin; ObjectAddress address = InvalidObjectAddress; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -3011,14 +3009,15 @@ AlterDomainAddConstraint(List *names, Node *newConstraint, if (!constr->skip_validation) validateDomainNotNullConstraint(domainoid); - typTup->typnotnull = true; - CatalogTupleUpdate(typrel, &tup->t_self, tup); + HeapTupleUpdateField(pg_type, typnotnull, true, typTup, updated); + CatalogTupleUpdate(typrel, &tup->t_self, tup, updated, NULL); } ObjectAddressSet(address, TypeRelationId, domainoid); /* Clean up */ table_close(typrel, RowExclusiveLock); + bms_free(updated); return address; } @@ -3045,6 +3044,7 @@ AlterDomainValidateConstraint(List *names, const char *constrName) HeapTuple copyTuple; ScanKeyData skey[3]; ObjectAddress address; + Bitmapset *updated = NULL; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -3110,8 +3110,8 @@ AlterDomainValidateConstraint(List *names, const char *constrName) */ copyTuple = heap_copytuple(tuple); copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple); - copy_con->convalidated = true; - CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple); + HeapTupleUpdateField(pg_constraint, convalidated, true, copy_con, updated); + CatalogTupleUpdate(conrel, ©Tuple->t_self, copyTuple, updated, NULL); InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0); @@ -3125,6 +3125,7 @@ AlterDomainValidateConstraint(List *names, const char *constrName) table_close(conrel, RowExclusiveLock); ReleaseSysCache(tup); + bms_free(updated); return address; } @@ -3999,9 +4000,9 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) Relation rel; HeapTuple tup; Form_pg_type typTup; - Datum repl_val[Natts_pg_type]; - bool repl_null[Natts_pg_type]; - bool repl_repl[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; Acl *newAcl; Datum aclDatum; bool isNull; @@ -4013,11 +4014,7 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) elog(ERROR, "cache lookup failed for type %u", typeOid); typTup = (Form_pg_type) GETSTRUCT(tup); - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - - repl_repl[Anum_pg_type_typowner - 1] = true; - repl_val[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(newOwnerId); + HeapTupleUpdateValue(pg_type, typowner, ObjectIdGetDatum(newOwnerId), values, nulls, updated); aclDatum = heap_getattr(tup, Anum_pg_type_typacl, @@ -4028,14 +4025,12 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) { newAcl = aclnewowner(DatumGetAclP(aclDatum), typTup->typowner, newOwnerId); - repl_repl[Anum_pg_type_typacl - 1] = true; - repl_val[Anum_pg_type_typacl - 1] = PointerGetDatum(newAcl); + HeapTupleUpdateValue(pg_type, typacl, PointerGetDatum(newAcl), values, nulls, updated); } - tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, - repl_repl); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); /* If it has an array type, update that too */ if (OidIsValid(typTup->typarray)) @@ -4056,6 +4051,7 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) /* Clean up */ table_close(rel, RowExclusiveLock); + bms_free(updated); } /* @@ -4176,6 +4172,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, Oid arrayOid; bool isCompositeType; ObjectAddress thisobj; + Bitmapset *updated = NULL; /* * Make sure we haven't moved this object previously. @@ -4241,9 +4238,9 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, /* OK, modify the pg_type row */ /* tup is a copy, so we can scribble directly on it */ - typform->typnamespace = nspOid; + HeapTupleUpdateField(pg_type, typnamespace, nspOid, typform, updated); - CatalogTupleUpdate(rel, &tup->t_self, tup); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); } /* @@ -4307,6 +4304,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, true, /* errorOnTableType */ objsMoved); + bms_free(updated); return oldNspOid; } @@ -4574,9 +4572,9 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray, HeapTuple tup, Relation catalog, AlterTypeRecurseParams *atparams) { - Datum values[Natts_pg_type]; - bool nulls[Natts_pg_type]; - bool replaces[Natts_pg_type]; + Datum values[Natts_pg_type] = {0}; + bool nulls[Natts_pg_type] = {false}; + Bitmapset *updated = NULL; HeapTuple newtup; SysScanDesc scan; ScanKeyData key[1]; @@ -4586,50 +4584,25 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray, check_stack_depth(); /* Update the current type's tuple */ - memset(values, 0, sizeof(values)); - memset(nulls, 0, sizeof(nulls)); - memset(replaces, 0, sizeof(replaces)); - if (atparams->updateStorage) - { - replaces[Anum_pg_type_typstorage - 1] = true; - values[Anum_pg_type_typstorage - 1] = CharGetDatum(atparams->storage); - } + HeapTupleUpdateValue(pg_type, typstorage, CharGetDatum(atparams->storage), values, nulls, updated); if (atparams->updateReceive) - { - replaces[Anum_pg_type_typreceive - 1] = true; - values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(atparams->receiveOid); - } + HeapTupleUpdateValue(pg_type, typreceive, ObjectIdGetDatum(atparams->receiveOid), values, nulls, updated); if (atparams->updateSend) - { - replaces[Anum_pg_type_typsend - 1] = true; - values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(atparams->sendOid); - } + HeapTupleUpdateValue(pg_type, typsend, ObjectIdGetDatum(atparams->sendOid), values, nulls, updated); if (atparams->updateTypmodin) - { - replaces[Anum_pg_type_typmodin - 1] = true; - values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(atparams->typmodinOid); - } + HeapTupleUpdateValue(pg_type, typmodin, ObjectIdGetDatum(atparams->typmodinOid), values, nulls, updated); if (atparams->updateTypmodout) - { - replaces[Anum_pg_type_typmodout - 1] = true; - values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(atparams->typmodoutOid); - } + HeapTupleUpdateValue(pg_type, typmodout, ObjectIdGetDatum(atparams->typmodoutOid), values, nulls, updated); if (atparams->updateAnalyze) - { - replaces[Anum_pg_type_typanalyze - 1] = true; - values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(atparams->analyzeOid); - } + HeapTupleUpdateValue(pg_type, typanalyze, ObjectIdGetDatum(atparams->analyzeOid), values, nulls, updated); if (atparams->updateSubscript) - { - replaces[Anum_pg_type_typsubscript - 1] = true; - values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(atparams->subscriptOid); - } + HeapTupleUpdateValue(pg_type, typsubscript, ObjectIdGetDatum(atparams->subscriptOid), values, nulls, updated); - newtup = heap_modify_tuple(tup, RelationGetDescr(catalog), - values, nulls, replaces); + newtup = heap_update_tuple(tup, RelationGetDescr(catalog), + values, nulls, updated); - CatalogTupleUpdate(catalog, &newtup->t_self, newtup); + CatalogTupleUpdate(catalog, &newtup->t_self, newtup, updated, NULL); /* Rebuild dependencies for this type */ GenerateTypeDependencies(newtup, @@ -4714,4 +4687,5 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray, } systable_endscan(scan); + bms_free(updated); } diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 6ae42ea565668..2bcfb7f5bc78c 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -134,8 +134,8 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) Relation pg_authid_rel; TupleDesc pg_authid_dsc; HeapTuple tuple; - Datum new_record[Natts_pg_authid] = {0}; - bool new_record_nulls[Natts_pg_authid] = {0}; + Datum values[Natts_pg_authid] = {0}; + bool nulls[Natts_pg_authid] = {false}; Oid currentUserId = GetUserId(); Oid roleid; ListCell *item; @@ -405,15 +405,14 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) /* * Build a tuple to insert */ - new_record[Anum_pg_authid_rolname - 1] = - DirectFunctionCall1(namein, CStringGetDatum(stmt->role)); - new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper); - new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit); - new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole); - new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb); - new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin); - new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication); - new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit); + HeapTupleSetValue(pg_authid, rolname, DirectFunctionCall1(namein, CStringGetDatum(stmt->role)), values); + HeapTupleSetValue(pg_authid, rolsuper, BoolGetDatum(issuper), values); + HeapTupleSetValue(pg_authid, rolinherit, BoolGetDatum(inherit), values); + HeapTupleSetValue(pg_authid, rolcreaterole, BoolGetDatum(createrole), values); + HeapTupleSetValue(pg_authid, rolcreatedb, BoolGetDatum(createdb), values); + HeapTupleSetValue(pg_authid, rolcanlogin, BoolGetDatum(canlogin), values); + HeapTupleSetValue(pg_authid, rolreplication, BoolGetDatum(isreplication), values); + HeapTupleSetValue(pg_authid, rolconnlimit, Int32GetDatum(connlimit), values); if (password) { @@ -437,24 +436,24 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) { ereport(NOTICE, (errmsg("empty string is not a valid password, clearing password"))); - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleSetValueNull(pg_authid, rolpassword, values, nulls); } else { /* Encrypt the password to the requested format. */ shadow_pass = encrypt_password(Password_encryption, stmt->role, password); - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(shadow_pass); + HeapTupleSetValue(pg_authid, rolpassword, CStringGetTextDatum(shadow_pass), values); } } else - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleSetValueNull(pg_authid, rolpassword, values, nulls); - new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum; - new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null; + HeapTupleSetValue(pg_authid, rolvaliduntil, validUntil_datum, values); + if (validUntil_null) + HeapTupleSetValueNull(pg_authid, rolvaliduntil, values, nulls); - new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls); + HeapTupleSetValue(pg_authid, rolbypassrls, BoolGetDatum(bypassrls), values); /* * pg_largeobject_metadata contains pg_authid.oid's, so we use the @@ -476,14 +475,14 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) Anum_pg_authid_oid); } - new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid); + HeapTupleSetValue(pg_authid, oid, ObjectIdGetDatum(roleid), values); - tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls); + tuple = heap_form_tuple(pg_authid_dsc, values, nulls); /* * Insert new record in the pg_authid table */ - CatalogTupleInsert(pg_authid_rel, tuple); + CatalogTupleInsert(pg_authid_rel, tuple, NULL); /* * Advance command counter so we can see new record; else tests in @@ -618,9 +617,9 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt) { - Datum new_record[Natts_pg_authid] = {0}; - bool new_record_nulls[Natts_pg_authid] = {0}; - bool new_record_repl[Natts_pg_authid] = {0}; + Datum values[Natts_pg_authid] = {0}; + bool nulls[Natts_pg_authid] = {false}; + Bitmapset *updated = NULL; Relation pg_authid_rel; TupleDesc pg_authid_dsc; HeapTuple tuple, @@ -870,45 +869,26 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) errdetail("The bootstrap superuser must have the %s attribute.", "SUPERUSER"))); - new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super); - new_record_repl[Anum_pg_authid_rolsuper - 1] = true; + HeapTupleUpdateValue(pg_authid, rolsuper, BoolGetDatum(should_be_super), values, nulls, updated); } if (dinherit) - { - new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(boolVal(dinherit->arg)); - new_record_repl[Anum_pg_authid_rolinherit - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolinherit, BoolGetDatum(boolVal(dinherit->arg)), values, nulls, updated); if (dcreaterole) - { - new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(boolVal(dcreaterole->arg)); - new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolcreaterole, BoolGetDatum(boolVal(dcreaterole->arg)), values, nulls, updated); if (dcreatedb) - { - new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(boolVal(dcreatedb->arg)); - new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolcreatedb, BoolGetDatum(boolVal(dcreatedb->arg)), values, nulls, updated); if (dcanlogin) - { - new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(boolVal(dcanlogin->arg)); - new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolcanlogin, BoolGetDatum(boolVal(dcanlogin->arg)), values, nulls, updated); if (disreplication) - { - new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(boolVal(disreplication->arg)); - new_record_repl[Anum_pg_authid_rolreplication - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolreplication, BoolGetDatum(boolVal(disreplication->arg)), values, nulls, updated); if (dconnlimit) - { - new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit); - new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolconnlimit, Int32GetDatum(connlimit), values, nulls, updated); /* password */ if (password) @@ -922,40 +902,33 @@ AlterRole(ParseState *pstate, AlterRoleStmt *stmt) { ereport(NOTICE, (errmsg("empty string is not a valid password, clearing password"))); - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleSetValueNull(pg_authid, rolpassword, values, nulls); } else { /* Encrypt the password to the requested format. */ shadow_pass = encrypt_password(Password_encryption, rolename, password); - new_record[Anum_pg_authid_rolpassword - 1] = - CStringGetTextDatum(shadow_pass); + HeapTupleUpdateValue(pg_authid, rolpassword, CStringGetTextDatum(shadow_pass), values, nulls, updated); } - new_record_repl[Anum_pg_authid_rolpassword - 1] = true; } /* unset password */ if (dpassword && dpassword->arg == NULL) - { - new_record_repl[Anum_pg_authid_rolpassword - 1] = true; - new_record_nulls[Anum_pg_authid_rolpassword - 1] = true; - } + HeapTupleUpdateValueNull(pg_authid, rolpassword, values, nulls, updated); /* valid until */ - new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum; - new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null; - new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true; + HeapTupleUpdateValue(pg_authid, rolvaliduntil, validUntil_datum, values, nulls, updated); + if (validUntil_null) + HeapTupleUpdateValueNull(pg_authid, rolvaliduntil, values, nulls, updated); if (dbypassRLS) - { - new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(boolVal(dbypassRLS->arg)); - new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true; - } + HeapTupleUpdateValue(pg_authid, rolbypassrls, BoolGetDatum(boolVal(dbypassRLS->arg)), values, nulls, updated); - new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple); + new_tuple = heap_update_tuple(tuple, pg_authid_dsc, values, + nulls, updated); + CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0); @@ -1339,10 +1312,9 @@ RenameRole(const char *oldname, const char *newname) Relation rel; Datum datum; bool isnull; - Datum repl_val[Natts_pg_authid]; - bool repl_null[Natts_pg_authid]; - bool repl_repl[Natts_pg_authid]; - int i; + Datum values[Natts_pg_authid] = {0}; + bool nulls[Natts_pg_authid] = {false}; + Bitmapset *updated = NULL; Oid roleid; ObjectAddress address; Form_pg_authid authform; @@ -1433,29 +1405,22 @@ RenameRole(const char *oldname, const char *newname) "CREATEROLE", "ADMIN", NameStr(authform->rolname)))); } - /* OK, construct the modified tuple */ - for (i = 0; i < Natts_pg_authid; i++) - repl_repl[i] = false; - - repl_repl[Anum_pg_authid_rolname - 1] = true; - repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein, - CStringGetDatum(newname)); - repl_null[Anum_pg_authid_rolname - 1] = false; + HeapTupleUpdateValue(pg_authid, rolname, DirectFunctionCall1(namein, CStringGetDatum(newname)), values, nulls, updated); datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull); if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5) { /* MD5 uses the username as salt, so just clear it on a rename */ - repl_repl[Anum_pg_authid_rolpassword - 1] = true; - repl_null[Anum_pg_authid_rolpassword - 1] = true; + HeapTupleUpdateValueNull(pg_authid, rolpassword, values, nulls, updated); ereport(NOTICE, (errmsg("MD5 password cleared because of role rename"))); } - newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl); - CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple); + newtuple = heap_update_tuple(oldtuple, dsc, values, nulls, updated); + CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0); @@ -1823,17 +1788,14 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, Oid memberid = lfirst_oid(iditem); HeapTuple authmem_tuple; HeapTuple tuple; - Datum new_record[Natts_pg_auth_members] = {0}; - bool new_record_nulls[Natts_pg_auth_members] = {0}; - bool new_record_repl[Natts_pg_auth_members] = {0}; + Datum values[Natts_pg_auth_members] = {0}; + bool nulls[Natts_pg_auth_members] = {false}; + Bitmapset *updated = NULL; /* Common initialization for possible insert or update */ - new_record[Anum_pg_auth_members_roleid - 1] = - ObjectIdGetDatum(roleid); - new_record[Anum_pg_auth_members_member - 1] = - ObjectIdGetDatum(memberid); - new_record[Anum_pg_auth_members_grantor - 1] = - ObjectIdGetDatum(grantorId); + HeapTupleUpdateValue(pg_auth_members, roleid, ObjectIdGetDatum(roleid), values, nulls, updated); + HeapTupleUpdateValue(pg_auth_members, member, ObjectIdGetDatum(memberid), values, nulls, updated); + HeapTupleUpdateValue(pg_auth_members, grantor, ObjectIdGetDatum(grantorId), values, nulls, updated); /* Find any existing tuple */ authmem_tuple = SearchSysCache3(AUTHMEMROLEMEM, @@ -1857,30 +1819,21 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, if ((popt->specified & GRANT_ROLE_SPECIFIED_ADMIN) != 0 && authmem_form->admin_option != popt->admin) { - new_record[Anum_pg_auth_members_admin_option - 1] = - BoolGetDatum(popt->admin); - new_record_repl[Anum_pg_auth_members_admin_option - 1] = - true; + HeapTupleUpdateValue(pg_auth_members, admin_option, BoolGetDatum(popt->admin), values, nulls, updated); at_least_one_change = true; } if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0 && authmem_form->inherit_option != popt->inherit) { - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(popt->inherit); - new_record_repl[Anum_pg_auth_members_inherit_option - 1] = - true; + HeapTupleUpdateValue(pg_auth_members, inherit_option, BoolGetDatum(popt->inherit), values, nulls, updated); at_least_one_change = true; } if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0 && authmem_form->set_option != popt->set) { - new_record[Anum_pg_auth_members_set_option - 1] = - BoolGetDatum(popt->set); - new_record_repl[Anum_pg_auth_members_set_option - 1] = - true; + HeapTupleUpdateValue(pg_auth_members, set_option, BoolGetDatum(popt->set), values, nulls, updated); at_least_one_change = true; } @@ -1894,10 +1847,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, continue; } - tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc, - new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple); + tuple = heap_update_tuple(authmem_tuple, pg_authmem_dsc, values, nulls, updated); + CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple, updated, NULL); ReleaseSysCache(authmem_tuple); } @@ -1911,10 +1862,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, * Either they were specified, or the defaults as set by * InitGrantRoleOptions are correct. */ - new_record[Anum_pg_auth_members_admin_option - 1] = - BoolGetDatum(popt->admin); - new_record[Anum_pg_auth_members_set_option - 1] = - BoolGetDatum(popt->set); + HeapTupleSetValue(pg_auth_members, admin_option, BoolGetDatum(popt->admin), values); + HeapTupleSetValue(pg_auth_members, set_option, BoolGetDatum(popt->set), values); /* * If the user specified a value for the inherit option, use @@ -1922,8 +1871,7 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, * on the role-level property. */ if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0) - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(popt->inherit); + HeapTupleSetValue(pg_auth_members, inherit_option, BoolGetDatum(popt->inherit), values); else { HeapTuple mrtup; @@ -1933,18 +1881,16 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, if (!HeapTupleIsValid(mrtup)) elog(ERROR, "cache lookup failed for role %u", memberid); mrform = (Form_pg_authid) GETSTRUCT(mrtup); - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(mrform->rolinherit); + HeapTupleSetValue(pg_auth_members, inherit_option, BoolGetDatum(mrform->rolinherit), values); ReleaseSysCache(mrtup); } /* get an OID for the new row and insert it */ objectId = GetNewOidWithIndex(pg_authmem_rel, AuthMemOidIndexId, Anum_pg_auth_members_oid); - new_record[Anum_pg_auth_members_oid - 1] = ObjectIdGetDatum(objectId); - tuple = heap_form_tuple(pg_authmem_dsc, - new_record, new_record_nulls); - CatalogTupleInsert(pg_authmem_rel, tuple); + HeapTupleSetValue(pg_auth_members, oid, ObjectIdGetDatum(objectId), values); + tuple = heap_form_tuple(pg_authmem_dsc, values, nulls); + CatalogTupleInsert(pg_authmem_rel, tuple, NULL); /* updateAclDependencies wants to pfree array inputs */ newmembers[0] = grantorId; @@ -1954,6 +1900,8 @@ AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, 1, newmembers); } + bms_free(updated); + /* CCI after each change, in case there are duplicates in list */ CommandCounterIncrement(); } @@ -1986,7 +1934,6 @@ DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, ListCell *iditem; CatCList *memlist; RevokeRoleGrantAction *actions; - int i; Assert(list_length(memberSpecs) == list_length(memberIds)); @@ -2034,7 +1981,7 @@ DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, * left alone, deleted, or just have the admin_option flag cleared. * Perform the appropriate action in each case. */ - for (i = 0; i < memlist->n_members; ++i) + for (int i = 0; i < memlist->n_members; ++i) { HeapTuple authmem_tuple; Form_pg_auth_members authmem_form; @@ -2059,39 +2006,24 @@ DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, { /* Just turn off the specified option */ HeapTuple tuple; - Datum new_record[Natts_pg_auth_members] = {0}; - bool new_record_nulls[Natts_pg_auth_members] = {0}; - bool new_record_repl[Natts_pg_auth_members] = {0}; + Datum values[Natts_pg_auth_members] = {0}; + bool nulls[Natts_pg_auth_members] = {false}; + Bitmapset *updated = NULL; /* Build a tuple to update with */ if (actions[i] == RRG_REMOVE_ADMIN_OPTION) - { - new_record[Anum_pg_auth_members_admin_option - 1] = - BoolGetDatum(false); - new_record_repl[Anum_pg_auth_members_admin_option - 1] = - true; - } + HeapTupleUpdateValue(pg_auth_members, admin_option, BoolGetDatum(false), values, nulls, updated); else if (actions[i] == RRG_REMOVE_INHERIT_OPTION) - { - new_record[Anum_pg_auth_members_inherit_option - 1] = - BoolGetDatum(false); - new_record_repl[Anum_pg_auth_members_inherit_option - 1] = - true; - } + HeapTupleUpdateValue(pg_auth_members, inherit_option, BoolGetDatum(false), values, nulls, updated); else if (actions[i] == RRG_REMOVE_SET_OPTION) - { - new_record[Anum_pg_auth_members_set_option - 1] = - BoolGetDatum(false); - new_record_repl[Anum_pg_auth_members_set_option - 1] = - true; - } + HeapTupleUpdateValue(pg_auth_members, set_option, BoolGetDatum(false), values, nulls, updated); else elog(ERROR, "unknown role revoke action"); - tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc, - new_record, - new_record_nulls, new_record_repl); - CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple); + tuple = heap_update_tuple(authmem_tuple, pg_authmem_dsc, + values, nulls, updated); + CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple, updated, NULL); + bms_free(updated); } } diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c index 4632aa8115d30..8b077b7b43f95 100644 --- a/src/backend/replication/logical/origin.c +++ b/src/backend/replication/logical/origin.c @@ -312,8 +312,8 @@ replorigin_create(const char *roname) for (roident = InvalidOid + 1; roident < PG_UINT16_MAX; roident++) { - bool nulls[Natts_pg_replication_origin]; - Datum values[Natts_pg_replication_origin]; + Datum values[Natts_pg_replication_origin] = {0}; + bool nulls[Natts_pg_replication_origin] = {false}; bool collides; CHECK_FOR_INTERRUPTS(); @@ -340,11 +340,11 @@ replorigin_create(const char *roname) */ memset(&nulls, 0, sizeof(nulls)); - values[Anum_pg_replication_origin_roident - 1] = ObjectIdGetDatum(roident); - values[Anum_pg_replication_origin_roname - 1] = roname_d; + HeapTupleSetValue(pg_replication_origin, roident, ObjectIdGetDatum(roident), values); + HeapTupleSetValue(pg_replication_origin, roname, roname_d, values); tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); - CatalogTupleInsert(rel, tuple); + CatalogTupleInsert(rel, tuple, NULL); CommandCounterIncrement(); break; } diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index dcc6124cc7308..6ca50840e473a 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -1651,9 +1651,9 @@ UpdateTwoPhaseState(Oid suboid, char new_state) { Relation rel; HeapTuple tup; - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; + Datum values[Natts_pg_subscription] = {0}; + bool nulls[Natts_pg_subscription] = {false}; + Bitmapset *updated = NULL; Assert(new_state == LOGICALREP_TWOPHASE_STATE_DISABLED || new_state == LOGICALREP_TWOPHASE_STATE_PENDING || @@ -1666,19 +1666,13 @@ UpdateTwoPhaseState(Oid suboid, char new_state) "cache lookup failed for subscription oid %u", suboid); - /* Form a new tuple. */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); - /* And update/set two_phase state */ - values[Anum_pg_subscription_subtwophasestate - 1] = CharGetDatum(new_state); - replaces[Anum_pg_subscription_subtwophasestate - 1] = true; + HeapTupleUpdateValue(pg_subscription, subtwophasestate, CharGetDatum(new_state), values, nulls, updated); - tup = heap_modify_tuple(tup, RelationGetDescr(rel), - values, nulls, replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + tup = heap_update_tuple(tup, RelationGetDescr(rel), values, nulls, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); - heap_freetuple(tup); table_close(rel, RowExclusiveLock); + bms_free(updated); + heap_freetuple(tup); } diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 93970c6af2948..8551609c97718 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -6121,21 +6121,12 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn) */ if (subform->subskiplsn == myskiplsn) { - bool nulls[Natts_pg_subscription]; - bool replaces[Natts_pg_subscription]; - Datum values[Natts_pg_subscription]; - - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replaces, false, sizeof(replaces)); + Bitmapset *updated = NULL; /* reset subskiplsn */ - values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(InvalidXLogRecPtr); - replaces[Anum_pg_subscription_subskiplsn - 1] = true; - - tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls, - replaces); - CatalogTupleUpdate(rel, &tup->t_self, tup); + HeapTupleUpdateField(pg_subscription, subskiplsn, LSNGetDatum(InvalidXLogRecPtr), subform, updated); + CatalogTupleUpdate(rel, &tup->t_self, tup, updated, NULL); + bms_free(updated); if (myskiplsn != finish_lsn) ereport(WARNING, diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index a96fbdc1ddd64..92f82081d257a 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -59,8 +59,8 @@ InsertRule(const char *rulname, { char *evqual = nodeToString(event_qual); char *actiontree = nodeToString((Node *) action); - Datum values[Natts_pg_rewrite]; - bool nulls[Natts_pg_rewrite] = {0}; + Datum values[Natts_pg_rewrite] = {0}; + bool nulls[Natts_pg_rewrite] = {false}; NameData rname; Relation pg_rewrite_desc; HeapTuple tup, @@ -69,18 +69,19 @@ InsertRule(const char *rulname, ObjectAddress myself, referenced; bool is_update = false; + Bitmapset *updated = NULL; /* * Set up *nulls and *values arrays */ namestrcpy(&rname, rulname); - values[Anum_pg_rewrite_rulename - 1] = NameGetDatum(&rname); - values[Anum_pg_rewrite_ev_class - 1] = ObjectIdGetDatum(eventrel_oid); - values[Anum_pg_rewrite_ev_type - 1] = CharGetDatum(evtype + '0'); - values[Anum_pg_rewrite_ev_enabled - 1] = CharGetDatum(RULE_FIRES_ON_ORIGIN); - values[Anum_pg_rewrite_is_instead - 1] = BoolGetDatum(evinstead); - values[Anum_pg_rewrite_ev_qual - 1] = CStringGetTextDatum(evqual); - values[Anum_pg_rewrite_ev_action - 1] = CStringGetTextDatum(actiontree); + HeapTupleUpdateValue(pg_rewrite, rulename, NameGetDatum(&rname), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_class, ObjectIdGetDatum(eventrel_oid), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_type, CharGetDatum(evtype + '0'), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_enabled, CharGetDatum(RULE_FIRES_ON_ORIGIN), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, is_instead, BoolGetDatum(evinstead), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_qual, CStringGetTextDatum(evqual), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_action, CStringGetTextDatum(actiontree), values, nulls, updated); /* * Ready to store new pg_rewrite tuple @@ -96,8 +97,6 @@ InsertRule(const char *rulname, if (HeapTupleIsValid(oldtup)) { - bool replaces[Natts_pg_rewrite] = {0}; - if (!replace) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), @@ -107,16 +106,14 @@ InsertRule(const char *rulname, /* * When replacing, we don't need to replace every attribute */ - replaces[Anum_pg_rewrite_ev_type - 1] = true; - replaces[Anum_pg_rewrite_is_instead - 1] = true; - replaces[Anum_pg_rewrite_ev_qual - 1] = true; - replaces[Anum_pg_rewrite_ev_action - 1] = true; - - tup = heap_modify_tuple(oldtup, RelationGetDescr(pg_rewrite_desc), - values, nulls, replaces); - - CatalogTupleUpdate(pg_rewrite_desc, &tup->t_self, tup); - + HeapTupleUpdateValue(pg_rewrite, ev_type, CharGetDatum(evtype + '0'), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, is_instead, BoolGetDatum(evinstead), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_qual, CStringGetTextDatum(evqual), values, nulls, updated); + HeapTupleUpdateValue(pg_rewrite, ev_action, CStringGetTextDatum(actiontree), values, nulls, updated); + + tup = heap_update_tuple(oldtup, RelationGetDescr(pg_rewrite_desc), + values, nulls, updated); + CatalogTupleUpdate(pg_rewrite_desc, &tup->t_self, tup, updated, NULL); ReleaseSysCache(oldtup); rewriteObjectId = ((Form_pg_rewrite) GETSTRUCT(tup))->oid; @@ -127,14 +124,12 @@ InsertRule(const char *rulname, rewriteObjectId = GetNewOidWithIndex(pg_rewrite_desc, RewriteOidIndexId, Anum_pg_rewrite_oid); - values[Anum_pg_rewrite_oid - 1] = ObjectIdGetDatum(rewriteObjectId); - + HeapTupleUpdateValue(pg_rewrite, oid, ObjectIdGetDatum(rewriteObjectId), values, nulls, updated); tup = heap_form_tuple(pg_rewrite_desc->rd_att, values, nulls); - - CatalogTupleInsert(pg_rewrite_desc, tup); + CatalogTupleInsert(pg_rewrite_desc, tup, NULL); } - + bms_free(updated); heap_freetuple(tup); /* If replacing, get rid of old dependencies and make new ones */ @@ -727,8 +722,11 @@ EnableDisableRule(Relation rel, const char *rulename, */ if (ruleform->ev_enabled != fires_when) { - ruleform->ev_enabled = fires_when; - CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup); + Bitmapset *updated = NULL; + + HeapTupleUpdateField(pg_rewrite, ev_enabled, fires_when, ruleform, updated); + CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup, updated, NULL); + bms_free(updated); changed = true; } @@ -799,6 +797,7 @@ RenameRewriteRule(RangeVar *relation, const char *oldName, Form_pg_rewrite ruleform; Oid ruleOid; ObjectAddress address; + Bitmapset *updated = NULL; /* * Look up name, check permissions, and acquire lock (which we will NOT @@ -845,8 +844,8 @@ RenameRewriteRule(RangeVar *relation, const char *oldName, /* OK, do the update */ namestrcpy(&(ruleform->rulename), newName); - - CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup); + CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup, updated, NULL); + bms_free(updated); InvokeObjectPostAlterHook(RewriteRelationId, ruleOid, 0); diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index e401c19594902..4d82c0c8e1626 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -18,6 +18,7 @@ #include "access/table.h" #include "catalog/indexing.h" #include "catalog/pg_class.h" +#include "nodes/bitmapset.h" #include "catalog/pg_rewrite.h" #include "rewrite/rewriteSupport.h" #include "utils/inval.h" @@ -68,9 +69,12 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules) if (classForm->relhasrules != relHasRules) { /* Do the update */ + Bitmapset *updated = NULL; + classForm->relhasrules = relHasRules; + updated = bms_add_member(updated, Anum_pg_class_relhasrules - FirstLowInvalidHeapAttributeNumber); - CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple); + CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple, updated, NULL); } else { diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c index ef4d768feab7e..817db4cdefb3e 100644 --- a/src/backend/statistics/attribute_stats.c +++ b/src/backend/statistics/attribute_stats.c @@ -18,6 +18,7 @@ #include "postgres.h" #include "access/heapam.h" +#include "access/htup.h" #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_collation.h" @@ -120,15 +121,15 @@ 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 Bitmapset *set_stats_slot(Datum *values, bool *nulls, Bitmapset *updated, + 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, - const Datum *values, const bool *nulls, const bool *replaces); + const Datum *values, const bool *nulls, const Bitmapset *updated); 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); +static Bitmapset *init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited, + Datum *values, bool *nulls, Bitmapset *updated); /* * Insert or Update Attribute Statistics @@ -184,9 +185,8 @@ attribute_statistics_update(FunctionCallInfo fcinfo) !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 nulls[Natts_pg_statistic] = {false}; + Bitmapset *updated = NULL; bool result = true; stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG); @@ -361,25 +361,17 @@ attribute_statistics_update(FunctionCallInfo fcinfo) if (HeapTupleIsValid(statup)) heap_deform_tuple(statup, RelationGetDescr(starel), values, nulls); else - init_empty_stats_tuple(reloid, attnum, inherited, values, nulls, - replaces); + updated = init_empty_stats_tuple(reloid, attnum, inherited, values, nulls, updated); /* 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; - } + HeapTupleUpdateValue(pg_statistic, stanullfrac, PG_GETARG_DATUM(NULL_FRAC_ARG), values, nulls, updated); + 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; - } + HeapTupleUpdateValue(pg_statistic, stawidth, PG_GETARG_DATUM(AVG_WIDTH_ARG), values, nulls, updated); + 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; - } + HeapTupleUpdateValue(pg_statistic, stadistinct, PG_GETARG_DATUM(N_DISTINCT_ARG), values, nulls, updated); /* STATISTIC_KIND_MCV */ if (do_mcv) @@ -394,10 +386,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo) if (converted) { - set_stats_slot(values, nulls, replaces, - STATISTIC_KIND_MCV, - eq_opr, atttypcoll, - stanumbers, false, stavalues, false); + updated = set_stats_slot(values, nulls, updated, + STATISTIC_KIND_MCV, + eq_opr, atttypcoll, + stanumbers, false, stavalues, false); } else result = false; @@ -417,10 +409,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo) if (converted) { - set_stats_slot(values, nulls, replaces, - STATISTIC_KIND_HISTOGRAM, - lt_opr, atttypcoll, - 0, true, stavalues, false); + updated = set_stats_slot(values, nulls, updated, + STATISTIC_KIND_HISTOGRAM, + lt_opr, atttypcoll, + 0, true, stavalues, false); } else result = false; @@ -433,10 +425,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo) 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); + updated = set_stats_slot(values, nulls, updated, + STATISTIC_KIND_CORRELATION, + lt_opr, atttypcoll, + stanumbers, false, 0, true); } /* STATISTIC_KIND_MCELEM */ @@ -454,10 +446,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo) if (converted) { - set_stats_slot(values, nulls, replaces, - STATISTIC_KIND_MCELEM, - elem_eq_opr, atttypcoll, - stanumbers, false, stavalues, false); + updated = set_stats_slot(values, nulls, updated, + STATISTIC_KIND_MCELEM, + elem_eq_opr, atttypcoll, + stanumbers, false, stavalues, false); } else result = false; @@ -468,10 +460,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo) { 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); + updated = set_stats_slot(values, nulls, updated, + STATISTIC_KIND_DECHIST, + elem_eq_opr, atttypcoll, + stanumbers, false, 0, true); } /* @@ -494,10 +486,10 @@ attribute_statistics_update(FunctionCallInfo fcinfo) if (converted) { - set_stats_slot(values, nulls, replaces, - STATISTIC_KIND_BOUNDS_HISTOGRAM, - InvalidOid, InvalidOid, - 0, true, stavalues, false); + updated = set_stats_slot(values, nulls, updated, + STATISTIC_KIND_BOUNDS_HISTOGRAM, + InvalidOid, InvalidOid, + 0, true, stavalues, false); } else result = false; @@ -521,20 +513,21 @@ attribute_statistics_update(FunctionCallInfo fcinfo) if (converted) { - set_stats_slot(values, nulls, replaces, - STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM, - Float8LessOperator, InvalidOid, - stanumbers, false, stavalues, false); + updated = set_stats_slot(values, nulls, updated, + STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM, + Float8LessOperator, InvalidOid, + stanumbers, false, stavalues, false); } else result = false; } - upsert_pg_statistic(starel, statup, values, nulls, replaces); + upsert_pg_statistic(starel, statup, values, nulls, updated); if (HeapTupleIsValid(statup)) ReleaseSysCache(statup); table_close(starel, RowExclusiveLock); + bms_free(updated); return result; } @@ -759,69 +752,63 @@ text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid, * 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, +static Bitmapset * +set_stats_slot(Datum *values, bool *nulls, Bitmapset *updated, int16 stakind, Oid staop, Oid stacoll, Datum stanumbers, bool stanumbers_isnull, Datum stavalues, bool stavalues_isnull) { - int slotidx; + int i = 0; 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++) + /* + * NOTE: This might seem odd, to be adding 'i' to the name of the field on + * these macros, but that's what we need to do here to find the proper + * slot offset and record the proper value into the updated bitmap. + * + * Example: HeapTupleValue(pg_statistic, stakind1 + i, values); + * + * Becomes: values[Anum_pg_statistic_stakind1 + i - 1]; + * + * The result is you're indexing the i'th value, exactly what we needed. + */ + + /* Find existing slot with given stakind */ + for (i = 0; i < STATISTIC_NUM_SLOTS; i++) { - stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx; + Datum d = HeapTupleValue(pg_statistic, stakind1 + i, values); + int16 v = DatumGetInt16(d); + + if (first_empty < 0 && v == 0) + first_empty = i; - if (first_empty < 0 && - DatumGetInt16(values[stakind_attnum]) == 0) - first_empty = slotidx; - if (DatumGetInt16(values[stakind_attnum]) == stakind) + if (v == stakind) break; } - if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0) - slotidx = first_empty; + if (i >= STATISTIC_NUM_SLOTS && first_empty >= 0) + i = first_empty; - if (slotidx >= STATISTIC_NUM_SLOTS) + if (i >= STATISTIC_NUM_SLOTS) ereport(ERROR, - (errmsg("maximum number of statistics slots exceeded: %d", - slotidx + 1))); + (errmsg("maximum number of statistics slots exceeded: %d", i + 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(HeapTupleValue(pg_statistic, stakind1 + i, values)) != stakind) + HeapTupleUpdateValue(pg_statistic, stakind1 + i, Int16GetDatum(stakind), values, nulls, updated); + + if (DatumGetInt16(HeapTupleValue(pg_statistic, staop1 + i, values)) != staop) + HeapTupleUpdateValue(pg_statistic, staop1 + i, ObjectIdGetDatum(staop), values, nulls, updated); + + if (DatumGetInt16(HeapTupleValue(pg_statistic, stacoll1 + i, values + i)) != stacoll) + HeapTupleUpdateValue(pg_statistic, stacoll1 + i, ObjectIdGetDatum(stacoll), values, nulls, updated); - 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; - } + HeapTupleUpdateValue(pg_statistic, stanumbers1 + i, stanumbers, values, nulls, updated); + 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; - } + HeapTupleUpdateValue(pg_statistic, stavalues1 + i, stavalues, values, nulls, updated); + + return updated; } /* @@ -829,20 +816,21 @@ set_stats_slot(Datum *values, bool *nulls, bool *replaces, */ static void upsert_pg_statistic(Relation starel, HeapTuple oldtup, - const Datum *values, const bool *nulls, const bool *replaces) + const Datum *values, const bool *nulls, const Bitmapset *updated) { HeapTuple newtup; if (HeapTupleIsValid(oldtup)) { - newtup = heap_modify_tuple(oldtup, RelationGetDescr(starel), - values, nulls, replaces); - CatalogTupleUpdate(starel, &newtup->t_self, newtup); + TupleDesc tupdesc = RelationGetDescr(starel); + + newtup = heap_update_tuple(oldtup, tupdesc, values, nulls, updated); + CatalogTupleUpdate(starel, &newtup->t_self, newtup, updated, NULL); } else { newtup = heap_form_tuple(RelationGetDescr(starel), values, nulls); - CatalogTupleInsert(starel, newtup); + CatalogTupleInsert(starel, newtup, NULL); } heap_freetuple(newtup); @@ -883,39 +871,38 @@ delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit) /* * Initialize values and nulls for a new stats tuple. */ -static void +static Bitmapset * init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited, - Datum *values, bool *nulls, bool *replaces) + Datum *values, bool *nulls, Bitmapset *updated) { + /* + * NOTE: It is customary to initialize the "nulls" array to all false (0) + * and later, when some field transitions from a value to NULL to mark + * that transition using the proper macro which will set the array + * position to true (1). Here we start with the assumption that all + * values will be set to NULL. + */ + HeapTupleUpdateSetAllColumnsUpdated(pg_statistic, updated); memset(nulls, true, sizeof(bool) * Natts_pg_statistic); - memset(replaces, true, sizeof(bool) * Natts_pg_statistic); /* must initialize non-NULL attributes */ + HeapTupleUpdateValue(pg_statistic, starelid, ObjectIdGetDatum(reloid), values, nulls, updated); + HeapTupleUpdateValue(pg_statistic, staattnum, Int16GetDatum(attnum), values, nulls, updated); + HeapTupleUpdateValue(pg_statistic, stainherit, BoolGetDatum(inherited), values, nulls, updated); - 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; + HeapTupleUpdateValue(pg_statistic, stanullfrac, DEFAULT_NULL_FRAC, values, nulls, updated); + HeapTupleUpdateValue(pg_statistic, stawidth, DEFAULT_AVG_WIDTH, values, nulls, updated); + HeapTupleUpdateValue(pg_statistic, stadistinct, DEFAULT_N_DISTINCT, values, nulls, updated); /* initialize stakind, staop, and stacoll slots */ - for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++) + for (int i = 0; i < STATISTIC_NUM_SLOTS; i++) { - values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0; - nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false; - values[Anum_pg_statistic_staop1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid); - nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false; - values[Anum_pg_statistic_stacoll1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid); - nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false; + HeapTupleUpdateValue(pg_statistic, stakind1 + i, (Datum) 0, values, nulls, updated); + HeapTupleUpdateValue(pg_statistic, staop1 + i, ObjectIdGetDatum(InvalidOid), values, nulls, updated); + HeapTupleUpdateValue(pg_statistic, stacoll1 + i, ObjectIdGetDatum(InvalidOid), values, nulls, updated); } + + return updated; } /* diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 3c3d2d315c6f4..7a6e6a2787b81 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -762,20 +762,14 @@ statext_store(Oid statOid, bool inh, { Relation pg_stextdata; HeapTuple stup; - Datum values[Natts_pg_statistic_ext_data]; - bool nulls[Natts_pg_statistic_ext_data]; + Datum values[Natts_pg_statistic_ext_data] = {0}; + bool nulls[Natts_pg_statistic_ext_data] = {false}; pg_stextdata = table_open(StatisticExtDataRelationId, RowExclusiveLock); - memset(nulls, true, sizeof(nulls)); - memset(values, 0, sizeof(values)); - /* basic info */ - values[Anum_pg_statistic_ext_data_stxoid - 1] = ObjectIdGetDatum(statOid); - nulls[Anum_pg_statistic_ext_data_stxoid - 1] = false; - - values[Anum_pg_statistic_ext_data_stxdinherit - 1] = BoolGetDatum(inh); - nulls[Anum_pg_statistic_ext_data_stxdinherit - 1] = false; + HeapTupleSetValue(pg_statistic_ext_data, stxoid, ObjectIdGetDatum(statOid), values); + HeapTupleSetValue(pg_statistic_ext_data, stxdinherit, BoolGetDatum(inh), values); /* * Construct a new pg_statistic_ext_data tuple, replacing the calculated @@ -785,29 +779,42 @@ statext_store(Oid statOid, bool inh, { bytea *data = statext_ndistinct_serialize(ndistinct); - nulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = (data == NULL); - values[Anum_pg_statistic_ext_data_stxdndistinct - 1] = PointerGetDatum(data); + if (data == NULL) + HeapTupleSetValueNull(pg_statistic_ext_data, stxdndistinct, values, nulls); + else + HeapTupleSetValue(pg_statistic_ext_data, stxdndistinct, PointerGetDatum(data), values); } + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxdndistinct, values, nulls); if (dependencies != NULL) { bytea *data = statext_dependencies_serialize(dependencies); - nulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = (data == NULL); - values[Anum_pg_statistic_ext_data_stxddependencies - 1] = PointerGetDatum(data); + if (data == NULL) + HeapTupleSetValueNull(pg_statistic_ext_data, stxddependencies, values, nulls); + else + HeapTupleSetValue(pg_statistic_ext_data, stxddependencies, PointerGetDatum(data), values); } + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxddependencies, values, nulls); + if (mcv != NULL) { bytea *data = statext_mcv_serialize(mcv, stats); - nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = (data == NULL); - values[Anum_pg_statistic_ext_data_stxdmcv - 1] = PointerGetDatum(data); + if (data == NULL) + HeapTupleSetValueNull(pg_statistic_ext_data, stxdmcv, values, nulls); + else + HeapTupleSetValue(pg_statistic_ext_data, stxdmcv, PointerGetDatum(data), values); } + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxdmcv, values, nulls); + if (exprs != (Datum) 0) - { - nulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = false; - values[Anum_pg_statistic_ext_data_stxdexpr - 1] = exprs; - } + HeapTupleSetValue(pg_statistic_ext_data, stxdexpr, exprs, values); + else + HeapTupleSetValueNull(pg_statistic_ext_data, stxdexpr, values, nulls); /* * Delete the old tuple if it exists, and insert a new one. It's easier @@ -817,7 +824,7 @@ statext_store(Oid statOid, bool inh, /* form and insert a new tuple */ stup = heap_form_tuple(RelationGetDescr(pg_stextdata), values, nulls); - CatalogTupleInsert(pg_stextdata, stup); + CatalogTupleInsert(pg_stextdata, stup, NULL); heap_freetuple(stup); @@ -2293,8 +2300,8 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs) k; VacAttrStats *stats = exprdata[exprno].vacattrstat; - Datum values[Natts_pg_statistic]; - bool nulls[Natts_pg_statistic]; + Datum values[Natts_pg_statistic] = {0}; + bool nulls[Natts_pg_statistic] = {false}; HeapTuple stup; if (!stats->stats_valid) @@ -2315,12 +2322,12 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs) nulls[i] = false; } - values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(InvalidAttrNumber); - values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(false); - values[Anum_pg_statistic_stanullfrac - 1] = Float4GetDatum(stats->stanullfrac); - values[Anum_pg_statistic_stawidth - 1] = Int32GetDatum(stats->stawidth); - values[Anum_pg_statistic_stadistinct - 1] = Float4GetDatum(stats->stadistinct); + HeapTupleSetValue(pg_statistic, starelid, ObjectIdGetDatum(InvalidOid), values); + HeapTupleSetValue(pg_statistic, staattnum, Int16GetDatum(InvalidAttrNumber), values); + HeapTupleSetValue(pg_statistic, stainherit, BoolGetDatum(false), values); + HeapTupleSetValue(pg_statistic, stanullfrac, Float4GetDatum(stats->stanullfrac), values); + HeapTupleSetValue(pg_statistic, stawidth, Int32GetDatum(stats->stawidth), values); + HeapTupleSetValue(pg_statistic, stadistinct, Float4GetDatum(stats->stadistinct), values); i = Anum_pg_statistic_stakind1 - 1; for (k = 0; k < STATISTIC_NUM_SLOTS; k++) { diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c index 174da7d93a505..790391b573dc1 100644 --- a/src/backend/statistics/relation_stats.c +++ b/src/backend/statistics/relation_stats.c @@ -18,6 +18,7 @@ #include "postgres.h" #include "access/heapam.h" +#include "access/htup.h" #include "catalog/indexing.h" #include "catalog/namespace.h" #include "nodes/makefuncs.h" @@ -79,10 +80,9 @@ relation_statistics_update(FunctionCallInfo fcinfo) 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; + Datum values[Natts_pg_class] = {0}; + bool nulls[Natts_pg_class] = {false}; + Bitmapset *updated = NULL; Oid locked_table = InvalidOid; stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG); @@ -146,42 +146,26 @@ relation_statistics_update(FunctionCallInfo fcinfo) pgcform = (Form_pg_class) GETSTRUCT(ctup); if (update_relpages && relpages != pgcform->relpages) - { - replaces[nreplaces] = Anum_pg_class_relpages; - values[nreplaces] = UInt32GetDatum(relpages); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, relpages, UInt32GetDatum(relpages), values, nulls, updated); if (update_reltuples && reltuples != pgcform->reltuples) - { - replaces[nreplaces] = Anum_pg_class_reltuples; - values[nreplaces] = Float4GetDatum(reltuples); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, reltuples, Float4GetDatum(reltuples), values, nulls, updated); if (update_relallvisible && relallvisible != pgcform->relallvisible) - { - replaces[nreplaces] = Anum_pg_class_relallvisible; - values[nreplaces] = UInt32GetDatum(relallvisible); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, relallvisible, UInt32GetDatum(relallvisible), values, nulls, updated); if (update_relallfrozen && relallfrozen != pgcform->relallfrozen) - { - replaces[nreplaces] = Anum_pg_class_relallfrozen; - values[nreplaces] = UInt32GetDatum(relallfrozen); - nreplaces++; - } + HeapTupleUpdateValue(pg_class, relallfrozen, UInt32GetDatum(relallfrozen), values, nulls, updated); - if (nreplaces > 0) + if (!bms_is_empty(updated)) { TupleDesc tupdesc = RelationGetDescr(crel); HeapTuple newtup; - newtup = heap_modify_tuple_by_cols(ctup, tupdesc, nreplaces, - replaces, values, nulls); - CatalogTupleUpdate(crel, &newtup->t_self, newtup); + newtup = heap_update_tuple(ctup, tupdesc, values, nulls, updated); + CatalogTupleUpdate(crel, &newtup->t_self, newtup, updated, NULL); heap_freetuple(newtup); + bms_free(updated); } ReleaseSysCache(ctup); diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index f6d2f9dba13d0..163c77e49272e 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -564,9 +564,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) } workbuf = {0}; char *workb = VARDATA(&workbuf.hdr); HeapTuple newtup; - Datum values[Natts_pg_largeobject]; - bool nulls[Natts_pg_largeobject]; - bool replace[Natts_pg_largeobject]; + Datum values[Natts_pg_largeobject] = {0}; + bool nulls[Natts_pg_largeobject] = {false}; CatalogIndexState indstate; Assert(obj_desc); @@ -612,6 +611,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) while (nwritten < nbytes) { + Bitmapset *updated = NULL; + /* * If possible, get next pre-existing page of the LO. We expect the * indexscan will deliver these in order --- but there may be holes. @@ -667,16 +668,11 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) /* * Form and insert updated tuple */ - memset(values, 0, sizeof(values)); - memset(nulls, false, sizeof(nulls)); - memset(replace, false, sizeof(replace)); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); - replace[Anum_pg_largeobject_data - 1] = true; - newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r), - values, nulls, replace); - CatalogTupleUpdateWithInfo(lo_heap_r, &newtup->t_self, newtup, - indstate); + HeapTupleUpdateValue(pg_largeobject, data, PointerGetDatum(&workbuf), values, nulls, updated); + newtup = heap_update_tuple(oldtuple, RelationGetDescr(lo_heap_r), values, nulls, updated); + CatalogTupleUpdate(lo_heap_r, &newtup->t_self, newtup, updated, indstate); heap_freetuple(newtup); + bms_free(updated); /* * We're done with this old page. @@ -713,11 +709,11 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id); - values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); + HeapTupleSetValue(pg_largeobject, loid, ObjectIdGetDatum(obj_desc->id), values); + HeapTupleSetValue(pg_largeobject, pageno, Int32GetDatum(pageno), values); + HeapTupleSetValue(pg_largeobject, data, PointerGetDatum(&workbuf), values); newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls); - CatalogTupleInsertWithInfo(lo_heap_r, newtup, indstate); + CatalogTupleInsert(lo_heap_r, newtup, indstate); heap_freetuple(newtup); } pageno++; @@ -755,9 +751,9 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len) } workbuf = {0}; char *workb = VARDATA(&workbuf.hdr); HeapTuple newtup; - Datum values[Natts_pg_largeobject]; - bool nulls[Natts_pg_largeobject]; - bool replace[Natts_pg_largeobject]; + Datum values[Natts_pg_largeobject] = {0}; + bool nulls[Natts_pg_largeobject] = {false}; + Bitmapset *updated = NULL; CatalogIndexState indstate; Assert(obj_desc); @@ -844,14 +840,11 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len) */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - memset(replace, false, sizeof(replace)); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); - replace[Anum_pg_largeobject_data - 1] = true; - newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r), - values, nulls, replace); - CatalogTupleUpdateWithInfo(lo_heap_r, &newtup->t_self, newtup, - indstate); + HeapTupleUpdateValue(pg_largeobject, data, PointerGetDatum(&workbuf), values, nulls, updated); + newtup = heap_update_tuple(oldtuple, RelationGetDescr(lo_heap_r), values, nulls, updated); + CatalogTupleUpdate(lo_heap_r, &newtup->t_self, newtup, updated, indstate); heap_freetuple(newtup); + bms_free(updated); } else { @@ -883,11 +876,11 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len) */ memset(values, 0, sizeof(values)); memset(nulls, false, sizeof(nulls)); - values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id); - values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); + HeapTupleSetValue(pg_largeobject, loid, ObjectIdGetDatum(obj_desc->id), values); + HeapTupleSetValue(pg_largeobject, pageno, Int32GetDatum(pageno), values); + HeapTupleSetValue(pg_largeobject, data, PointerGetDatum(&workbuf), values); newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls); - CatalogTupleInsertWithInfo(lo_heap_r, newtup, indstate); + CatalogTupleInsert(lo_heap_r, newtup, indstate); heap_freetuple(newtup); } diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 915d0bc908423..61d3b760e15e7 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -3780,6 +3780,7 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) MultiXactId minmulti = InvalidMultiXactId; TransactionId freezeXid = InvalidTransactionId; RelFileLocator newrlocator; + Bitmapset *updated = NULL; if (!IsBinaryUpgrade) { @@ -3929,21 +3930,21 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) else { /* Normal case, update the pg_class entry */ - classform->relfilenode = newrelfilenumber; + HeapTupleUpdateField(pg_class, relfilenode, newrelfilenumber, classform, updated); /* relpages etc. never change for sequences */ if (relation->rd_rel->relkind != RELKIND_SEQUENCE) { - classform->relpages = 0; /* it's empty until further notice */ - classform->reltuples = -1; - classform->relallvisible = 0; - classform->relallfrozen = 0; + HeapTupleUpdateField(pg_class, relpages, 0, classform, updated); + HeapTupleUpdateField(pg_class, reltuples, -1, classform, updated); + HeapTupleUpdateField(pg_class, relallvisible, 0, classform, updated); + HeapTupleUpdateField(pg_class, relallfrozen, 0, classform, updated); } - classform->relfrozenxid = freezeXid; - classform->relminmxid = minmulti; - classform->relpersistence = persistence; + HeapTupleUpdateField(pg_class, relfrozenxid, freezeXid, classform, updated); + HeapTupleUpdateField(pg_class, relminmxid, minmulti, classform, updated); + HeapTupleUpdateField(pg_class, relpersistence, persistence, classform, updated); - CatalogTupleUpdate(pg_class, &otid, tuple); + CatalogTupleUpdate(pg_class, &otid, tuple, updated, NULL); } UnlockTuple(pg_class, &otid, InplaceUpdateTupleLock); @@ -3958,6 +3959,7 @@ RelationSetNewRelfilenumber(Relation relation, char persistence) CommandCounterIncrement(); RelationAssumeNewRelfilelocator(relation); + bms_free(updated); } /* diff --git a/src/include/access/htup.h b/src/include/access/htup.h index f6b766697e297..e67bb718efa46 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -14,6 +14,7 @@ #ifndef HTUP_H #define HTUP_H +#include "catalog/pg_aggregate_d.h" #include "storage/itemptr.h" /* typedefs and forward declarations for structs defined in htup_details.h */ @@ -77,6 +78,66 @@ typedef HeapTupleData *HeapTuple; */ #define HeapTupleIsValid(tuple) ((tuple) != NULL) +#define HeapTupleValue(table_name, field, values) \ + (values)[Anum_##table_name##_##field - 1] + +/* + * These are useful when forming tuples for CatalogTupleInsert() + */ + +#define HeapTupleSetField(table_name, field, value, form_ptr) \ + (form_ptr)->field = (value) + +#define HeapTupleSetFieldNull(table_name, field, nulls) \ + (nulls)[Anum_##table_name##_##field - 1] = true + +#define HeapTupleSetValue(table_name, field, value, values) \ + (values)[Anum_##table_name##_##field - 1] = (value) + +#define HeapTupleSetValueNull(table_name, field, values, nulls) \ + do { \ + (values)[Anum_##table_name##_##field - 1] = (Datum) 0; \ + (nulls)[Anum_##table_name##_##field - 1] = true; \ + } while(0) + +/* + * These are useful when forming tuples for CatalogTupleUpdate() + * + * Updated catalog tuples need to track which fields were changed when + * calling heap_update_tuple(), so we use a bitmap to keep track of that. + */ +#define HeapTupleMarkColumnUpdated(table_name, field, updated) \ + (updated) = bms_add_member((updated), \ + Anum_##table_name##_##field - FirstLowInvalidHeapAttributeNumber) + +#define HeapTupleUpdateSetAllColumnsUpdated(table_name, updated) \ + (updated) = bms_add_range((updated), 1 - FirstLowInvalidHeapAttributeNumber, \ + Natts_##table_name - FirstLowInvalidHeapAttributeNumber) + +#define HeapTupleSetColumnNotUpdated(table_name, field, updated) \ + (updated) = bms_del_member((updated), \ + Anum_##table_name##_##field - FirstLowInvalidHeapAttributeNumber) + +#define HeapTupleUpdateField(table_name, field, value, form_ptr, updated) \ + do { \ + (form_ptr)->field = (value); \ + HeapTupleMarkColumnUpdated(table_name, field, updated); \ + } while(0) + +#define HeapTupleUpdateValue(table_name, field, value, values, nulls, updated) \ + do { \ + (values)[Anum_##table_name##_##field - 1] = (Datum) (value); \ + (nulls)[Anum_##table_name##_##field - 1] = false; \ + HeapTupleMarkColumnUpdated(table_name, field, updated); \ + } while(0) + +#define HeapTupleUpdateValueNull(table_name, field, values, nulls, updated) \ + do { \ + (values)[Anum_##table_name##_##field - 1] = (Datum) 0; \ + (nulls)[Anum_##table_name##_##field - 1] = true; \ + HeapTupleMarkColumnUpdated(table_name, field, updated); \ + } while(0) + /* HeapTupleHeader functions implemented in utils/time/combocid.c */ extern CommandId HeapTupleHeaderGetCmin(const HeapTupleHeaderData *tup); extern CommandId HeapTupleHeaderGetCmax(const HeapTupleHeaderData *tup); diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index f3593acc8c2eb..814d764ee974b 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -21,6 +21,9 @@ #include "storage/bufpage.h" #include "varatt.h" +/* Forward declarations */ +typedef struct Bitmapset Bitmapset; + /* * MaxTupleAttributeNumber limits the number of (user) columns in a tuple. * The key limit on this value is that the size of the fixed overhead for @@ -835,6 +838,11 @@ extern HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, const int *replCols, const Datum *replValues, const bool *replIsnull); +extern HeapTuple heap_update_tuple(HeapTuple tuple, + TupleDesc tupleDesc, + const Datum *replValues, + const bool *replIsnull, + const Bitmapset *replaces); extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull); extern void heap_freetuple(HeapTuple htup); diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index 77c17d3fb7acc..685ff3d2bd176 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -37,18 +37,13 @@ typedef struct ResultRelInfo *CatalogIndexState; */ extern CatalogIndexState CatalogOpenIndexes(Relation heapRel); extern void CatalogCloseIndexes(CatalogIndexState indstate); -extern void CatalogTupleInsert(Relation heapRel, HeapTuple tup); -extern void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, - CatalogIndexState indstate); -extern void CatalogTuplesMultiInsertWithInfo(Relation heapRel, - TupleTableSlot **slot, - int ntuples, - CatalogIndexState indstate); +extern void CatalogTupleInsert(Relation heapRel, HeapTuple tup, + CatalogIndexState indstate); +extern void CatalogTuplesMultiInsert(Relation heapRel, TupleTableSlot **slot, + int ntuples, CatalogIndexState indstate); extern void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, - HeapTuple tup); -extern void CatalogTupleUpdateWithInfo(Relation heapRel, - const ItemPointerData *otid, HeapTuple tup, - CatalogIndexState indstate); + HeapTuple tuple, const struct Bitmapset *updated, + CatalogIndexState indstate); extern void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid); #endif /* INDEXING_H */ diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index efc41fca2ba79..0a8fc7f181c25 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -1232,7 +1232,7 @@ spawn_process(const char *cmdline) char *cmdline2; cmdline2 = psprintf("exec %s", cmdline); - execl(shellprog, shellprog, "-c", cmdline2, (char *) NULL); + execlp(shellprog, shellprog, "-c", cmdline2, (char *) NULL); /* Not using the normal bail() here as we want _exit */ bail_noatexit("could not exec \"%s\": %m", shellprog); } diff --git a/src/tools/pgindent/pgindent b/src/tools/pgindent/pgindent index d14da3f01a995..18ef572a8be6c 100755 --- a/src/tools/pgindent/pgindent +++ b/src/tools/pgindent/pgindent @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl # Copyright (c) 2021-2025, PostgreSQL Global Development Group