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