On 04.02.26 11:46, Peter Eisentraut wrote:
On 20.01.26 10:37, Peter Eisentraut wrote:
Currently, when the argument of copyObject() is const-qualified, the
return type is also, because the use of typeof carries over all the
qualifiers. This is incorrect, since the point of copyObject() is to
make a copy to mutate. But apparently no code ran into it.
The new implementation uses typeof_unqual, which drops the qualifiers,
making this work correctly.
typeof_unqual is standardized in C23, but all recent versions of all
the usual compilers support it even in non-C23 mode, at least as
__typeof_unqual__. We add a configure/meson test for typeof_unqual
and __typeof_unqual__ and use it if it's available, else we use the
existing fallback of just returning void *.
I committed this first part, but it ran into some trouble on the buildfarm:
https://buildfarm.postgresql.org/cgi-bin/show_log.pl?
nm=taipan&dt=2026-02-04%2008%3A39%3A34
The problem is that configure detected that gcc supports typeof_unqual,
but the clang used to produce the .bc files does not.
Here is a new version, after the previous one was reverted.
This is rebased over commit 1887d822f14 and now also provides a C++
implementation, corresponding to the C++ typeof implementation added by
that commit.
This revealed an insufficiency in that commit, which I fix in the first
patch.
I have addressed the above problem by swapping the order of the probes
(putting the underscore variant first), as discussed.
There was also an issue that newer MSVC versions claimed to support
typeof_unqual but it didn't work correctly. I have enhanced the
configure probes to detect this problem.From f2f750f7c3ab6b73514ab2fd5f02185abe9ad59f Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Fri, 6 Mar 2026 13:31:01 +0100
Subject: [PATCH v2 1/3] Fixes for C++ typeof implementation
This fixes two bugs in commit 1887d822f14.
First, if we are using the fallback C++ implementation of typeof, then
we need to include the C++ header <type_traits> for
std::remove_reference_t. This header is also likely to be used for
other C++ implementations of type tricks, so we'll put it into the
global includes.
Second, for the case that the C compiler supports typeof in a spelling
that is not "typeof" (for example, __typeof__), then we need to #undef
typeof in the C++ section to avoid warnings about duplicate macro
definitions.
---
src/include/c.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/include/c.h b/src/include/c.h
index f66c752d4a0..5b678283469 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -82,6 +82,14 @@
#endif
#ifdef ENABLE_NLS
#include <libintl.h>
+#endif
+
+#ifdef __cplusplus
+extern "C++"
+{
+/* This header is used in the definition of various C++ things below. */
+#include <type_traits>
+}
#endif
/* Pull in fundamental symbols that we also expose to applications */
@@ -435,6 +443,7 @@
* [1]:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm#existing-decltype
*/
#if defined(__cplusplus)
+#undef typeof
#ifdef pg_cxx_typeof
#define typeof(x) pg_cxx_typeof(x)
#elif !defined(HAVE_CXX_TYPEOF)
--
2.53.0
From d57d96e3929cd7ef2484e9d3ac95b1c9ba774823 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Fri, 6 Mar 2026 17:29:36 +0100
Subject: [PATCH v2 2/3] Change copyObject() to use typeof_unqual
Currently, when the argument of copyObject() is const-qualified, the
return type is also, because the use of typeof carries over all the
qualifiers. This is incorrect, since the point of copyObject() is to
make a copy to mutate. But apparently no code ran into it.
The new implementation uses typeof_unqual, which drops the qualifiers,
making this work correctly.
typeof_unqual is standardized in C23, but all recent versions of all
the usual compilers support it even in non-C23 mode, at least as
__typeof_unqual__. We add a configure/meson test for typeof_unqual
and __typeof_unqual__ and use it if it's available, else we use the
existing fallback of just returning void *.
We test the underscore variant first so that there is a higher chance
that clang used for bitcode also supports it, since we don't test that
separately.
Unlike the typeof test, the typeof_unqual test also tests with a void
pointer similar to how copyObject() would use it, because that is not
handled by MSVC, so we want the test to fail there.
Reviewed-by: David Geier <[email protected]>
Discussion:
https://www.postgresql.org/message-id/flat/92f9750f-c7f6-42d8-9a4a-85a3cbe808f3%40eisentraut.org
---
config/c-compiler.m4 | 65 +++++++++++
configure | 108 ++++++++++++++++++
configure.ac | 2 +
meson.build | 62 ++++++++++
src/include/c.h | 12 ++
src/include/nodes/nodes.h | 4 +-
src/include/pg_config.h.in | 14 +++
.../test_cplusplusext/test_cplusplusext.cpp | 3 +-
8 files changed, 267 insertions(+), 3 deletions(-)
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 5fd768b7332..88333ef301d 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -176,6 +176,40 @@ if test "$pgac_cv_c_typeof" != no; then
fi])# PGAC_C_TYPEOF
+# PGAC_C_TYPEOF_UNQUAL
+# --------------------
+# Check if the C compiler understands typeof_unqual or a variant. Define
+# HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word.
+#
+AC_DEFUN([PGAC_C_TYPEOF_UNQUAL],
+[AC_CACHE_CHECK(for typeof_unqual, pgac_cv_c_typeof_unqual,
+[pgac_cv_c_typeof_unqual=no
+# Test the underscore variant first so that there is a higher chance
+# that clang used for bitcode also supports it, since we don't test
+# that separately.
+#
+# Test with a void pointer, because MSVC doesn't handle that, and we
+# need that for copyObject().
+for pgac_kw in __typeof_unqual__ typeof_unqual; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+[int x = 0;
+$pgac_kw(x) y;
+const void *a;
+void *b;
+y = x;
+b = ($pgac_kw(*a) *) a;
+return y;])],
+[pgac_cv_c_typeof_unqual=$pgac_kw])
+ test "$pgac_cv_c_typeof_unqual" != no && break
+done])
+if test "$pgac_cv_c_typeof_unqual" != no; then
+ AC_DEFINE(HAVE_TYPEOF_UNQUAL, 1,
+ [Define to 1 if your compiler understands `typeof_unqual' or
something similar.])
+ if test "$pgac_cv_c_typeof_unqual" != typeof_unqual; then
+ AC_DEFINE_UNQUOTED(typeof_unqual, $pgac_cv_c_typeof_unqual, [Define to how
the compiler spells `typeof_unqual'.])
+ fi
+fi])# PGAC_C_TYPEOF_UNQUAL
+
# PGAC_CXX_TYPEOF
# ----------------
@@ -205,6 +239,37 @@ if test "$pgac_cv_cxx_typeof" != no; then
fi])# PGAC_CXX_TYPEOF
+# PGAC_CXX_TYPEOF_UNQUAL
+# ----------------------
+# Check if the C++ compiler understands typeof_unqual or a variant. Define
+# HAVE_CXX_TYPEOF_UNQUAL if so, and define 'pg_cxx_typeof_unqual' to the
actual key word.
+#
+AC_DEFUN([PGAC_CXX_TYPEOF_UNQUAL],
+[AC_CACHE_CHECK(for C++ typeof_unqual, pgac_cv_cxx_typeof_unqual,
+[pgac_cv_cxx_typeof_unqual=no
+AC_LANG_PUSH(C++)
+for pgac_kw in __typeof_unqual__ typeof_unqual; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
+[int x = 0;
+$pgac_kw(x) y;
+const void *a;
+void *b;
+y = x;
+b = ($pgac_kw(*a) *) a;
+return y;])],
+[pgac_cv_cxx_typeof_unqual=$pgac_kw])
+ test "$pgac_cv_cxx_typeof_unqual" != no && break
+done
+AC_LANG_POP([])])
+if test "$pgac_cv_cxx_typeof_unqual" != no; then
+ AC_DEFINE(HAVE_CXX_TYPEOF_UNQUAL, 1,
+ [Define to 1 if your C++ compiler understands `typeof_unqual' or
something similar.])
+ if test "$pgac_cv_cxx_typeof_unqual" != typeof_unqual; then
+ AC_DEFINE_UNQUOTED(pg_cxx_typeof_unqual, $pgac_cv_cxx_typeof_unqual,
[Define to how the C++ compiler spells `typeof_unqual'.])
+ fi
+fi])# PGAC_CXX_TYPEOF_UNQUAL
+
+
# PGAC_C_TYPES_COMPATIBLE
# -----------------------
diff --git a/configure b/configure
index 4aaaf92ba0a..bef63a8c595 100755
--- a/configure
+++ b/configure
@@ -15101,6 +15101,114 @@ _ACEOF
fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for typeof_unqual" >&5
+$as_echo_n "checking for typeof_unqual... " >&6; }
+if ${pgac_cv_c_typeof_unqual+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ pgac_cv_c_typeof_unqual=no
+# Test the underscore variant first so that there is a higher chance
+# that clang used for bitcode also supports it, since we don't test
+# that separately.
+#
+# Test with a void pointer, because MSVC doesn't handle that, and we
+# need that for copyObject().
+for pgac_kw in __typeof_unqual__ typeof_unqual; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int x = 0;
+$pgac_kw(x) y;
+const void *a;
+void *b;
+y = x;
+b = ($pgac_kw(*a) *) a;
+return y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ pgac_cv_c_typeof_unqual=$pgac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$pgac_cv_c_typeof_unqual" != no && break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_c_typeof_unqual" >&5
+$as_echo "$pgac_cv_c_typeof_unqual" >&6; }
+if test "$pgac_cv_c_typeof_unqual" != no; then
+
+$as_echo "#define HAVE_TYPEOF_UNQUAL 1" >>confdefs.h
+
+ if test "$pgac_cv_c_typeof_unqual" != typeof_unqual; then
+
+cat >>confdefs.h <<_ACEOF
+#define typeof_unqual $pgac_cv_c_typeof_unqual
+_ACEOF
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ typeof_unqual" >&5
+$as_echo_n "checking for C++ typeof_unqual... " >&6; }
+if ${pgac_cv_cxx_typeof_unqual+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ pgac_cv_cxx_typeof_unqual=no
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS
conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+for pgac_kw in __typeof_unqual__ typeof_unqual; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int x = 0;
+$pgac_kw(x) y;
+const void *a;
+void *b;
+y = x;
+b = ($pgac_kw(*a) *) a;
+return y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ pgac_cv_cxx_typeof_unqual=$pgac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$pgac_cv_cxx_typeof_unqual" != no && break
+done
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext
$LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_cxx_typeof_unqual"
>&5
+$as_echo "$pgac_cv_cxx_typeof_unqual" >&6; }
+if test "$pgac_cv_cxx_typeof_unqual" != no; then
+
+$as_echo "#define HAVE_CXX_TYPEOF_UNQUAL 1" >>confdefs.h
+
+ if test "$pgac_cv_cxx_typeof_unqual" != typeof_unqual; then
+
+cat >>confdefs.h <<_ACEOF
+#define pg_cxx_typeof_unqual $pgac_cv_cxx_typeof_unqual
+_ACEOF
+
+ fi
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for
__builtin_types_compatible_p" >&5
$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
if ${pgac_cv__types_compatible+:} false; then :
diff --git a/configure.ac b/configure.ac
index 9bc457bac87..4d3c69b1c4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1732,6 +1732,8 @@ PGAC_PRINTF_ARCHETYPE
PGAC_CXX_PRINTF_ARCHETYPE
PGAC_C_TYPEOF
PGAC_CXX_TYPEOF
+PGAC_C_TYPEOF_UNQUAL
+PGAC_CXX_TYPEOF_UNQUAL
PGAC_C_TYPES_COMPATIBLE
PGAC_C_BUILTIN_CONSTANT_P
PGAC_C_BUILTIN_OP_OVERFLOW
diff --git a/meson.build b/meson.build
index 2df54409ca6..70dc64c349a 100644
--- a/meson.build
+++ b/meson.build
@@ -2965,6 +2965,68 @@ int main(void)
endforeach
endif
+# Check if the C compiler understands typeof_unqual or a variant. Define
+# HAVE_TYPEOF_UNQUAL if so, and define 'typeof_unqual' to the actual key word.
+#
+# Test the underscore variant first so that there is a higher chance
+# that clang used for bitcode also supports it, since we don't test
+# that separately.
+#
+# Test with a void pointer, because MSVC doesn't handle that, and we
+# need that for copyObject().
+foreach kw : ['__typeof_unqual__', 'typeof_unqual']
+ if cc.compiles('''
+int main(void)
+{
+ int x = 0;
+ @0@(x) y;
+ const void *a;
+ void *b;
+ y = x;
+ b = (@0@(*a) *) a;
+ return y;
+}
+'''.format(kw),
+ name: kw,
+ args: test_c_args, include_directories: postgres_inc)
+
+ cdata.set('HAVE_TYPEOF_UNQUAL', 1)
+ if kw != 'typeof_unqual'
+ cdata.set('typeof_unqual', kw)
+ endif
+
+ break
+ endif
+endforeach
+
+# Check if the C++ compiler understands typeof_unqual or a variant.
+if have_cxx
+ foreach kw : ['__typeof_unqual__', 'typeof_unqual']
+ if cxx.compiles('''
+int main(void)
+{
+ int x = 0;
+ @0@(x) y;
+ const void *a;
+ void *b;
+ y = x;
+ b = (@0@(*a) *) a;
+ return y;
+}
+'''.format(kw),
+ name: 'C++ ' + kw,
+ args: test_c_args, include_directories: postgres_inc)
+
+ cdata.set('HAVE_CXX_TYPEOF_UNQUAL', 1)
+ if kw != 'typeof_unqual'
+ cdata.set('pg_cxx_typeof_unqual', kw)
+ endif
+
+ break
+ endif
+ endforeach
+endif
+
# MSVC doesn't cope well with defining restrict to __restrict, the
# spelling it understands, because it conflicts with
diff --git a/src/include/c.h b/src/include/c.h
index 5b678283469..2aab74d8b0e 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -452,7 +452,19 @@ extern "C++"
#ifndef HAVE_TYPEOF
#define HAVE_TYPEOF 1
#endif
+/*
+ * and analogously for typeof_unqual
+ */
+#undef typeof_unqual
+#ifdef pg_cxx_typeof_unqual
+#define typeof_unqual(x) pg_cxx_typeof_unqual(x)
+#elif !defined(HAVE_CXX_TYPEOF_UNQUAL)
+#define typeof_unqual(x) std::remove_cv_t<std::remove_reference_t<decltype(x)>>
+#endif
+#ifndef HAVE_TYPEOF_UNQUAL
+#define HAVE_TYPEOF_UNQUAL 1
#endif
+#endif /* __cplusplus */
/*
* CppAsString
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 59a7df31aba..a2925ae4946 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -226,8 +226,8 @@ extern int16 *readAttrNumberCols(int numCols);
extern void *copyObjectImpl(const void *from);
/* cast result back to argument type, if supported by compiler */
-#ifdef HAVE_TYPEOF
-#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#ifdef HAVE_TYPEOF_UNQUAL
+#define copyObject(obj) ((typeof_unqual(*(obj)) *) copyObjectImpl(obj))
#else
#define copyObject(obj) copyObjectImpl(obj)
#endif
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index cb0f53fade4..79379a4d125 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -73,6 +73,10 @@
*/
#undef HAVE_CXX_TYPEOF
+/* Define to 1 if your C++ compiler understands `typeof_unqual' or something
+ similar. */
+#undef HAVE_CXX_TYPEOF_UNQUAL
+
/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
don't. */
#undef HAVE_DECL_FDATASYNC
@@ -458,6 +462,10 @@
/* Define to 1 if your compiler understands `typeof' or something similar. */
#undef HAVE_TYPEOF
+/* Define to 1 if your compiler understands `typeof_unqual' or something
+ similar. */
+#undef HAVE_TYPEOF_UNQUAL
+
/* Define to 1 if you have the <uchar.h> header file. */
#undef HAVE_UCHAR_H
@@ -784,6 +792,9 @@
/* Define to how the C++ compiler spells `typeof'. */
#undef pg_cxx_typeof
+/* Define to how the C++ compiler spells `typeof_unqual'. */
+#undef pg_cxx_typeof_unqual
+
/* Define to keyword to use for C99 restrict support, or to nothing if not
supported */
#undef pg_restrict
@@ -804,3 +815,6 @@
/* Define to how the compiler spells `typeof'. */
#undef typeof
+
+/* Define to how the compiler spells `typeof_unqual'. */
+#undef typeof_unqual
diff --git a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
index ea04a761184..93cd7dd07f7 100644
--- a/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
+++ b/src/test/modules/test_cplusplusext/test_cplusplusext.cpp
@@ -37,7 +37,8 @@ test_cplusplus_add(PG_FUNCTION_ARGS)
int32 a = PG_GETARG_INT32(0);
int32 b = PG_GETARG_INT32(1);
RangeTblRef *node = makeNode(RangeTblRef);
- RangeTblRef *copy = copyObject(node);
+ const RangeTblRef *nodec = node;
+ RangeTblRef *copy = copyObject(nodec);
List *list = list_make1(node);
foreach_ptr(RangeTblRef, rtr, list)
--
2.53.0
From fe2a62a7b8bad4ce62393ac08af67d81aee962ac Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Wed, 4 Feb 2026 08:58:02 +0100
Subject: [PATCH v2 3/3] Add some const qualifiers enabled by typeof_unqual
change on copyObject
The recent commit to change copyObject() to use typeof_unqual allows
cleaning up some APIs to take advantage of this improved qualifier
handling. EventTriggerCollectSimpleCommand() is a good example: It
takes a node tree and makes a copy that it keeps around for its
internal purposes, but it can't communicate via its function signature
that it promises not scribble on the passed node tree. That is now
fixed.
Reviewed-by: David Geier <[email protected]>
Discussion:
https://www.postgresql.org/message-id/flat/92f9750f-c7f6-42d8-9a4a-85a3cbe808f3%40eisentraut.org
---
src/backend/catalog/index.c | 2 +-
src/backend/commands/event_trigger.c | 14 +++++++-------
src/backend/commands/indexcmds.c | 4 ++--
src/backend/commands/trigger.c | 4 ++--
src/backend/optimizer/prep/prepjointree.c | 4 ++--
src/backend/partitioning/partprune.c | 12 ++++++------
src/backend/rewrite/rewriteManip.c | 17 ++++++++++-------
src/backend/utils/cache/plancache.c | 2 +-
src/include/commands/defrem.h | 2 +-
src/include/commands/event_trigger.h | 14 +++++++-------
src/include/commands/trigger.h | 4 ++--
src/include/rewrite/rewriteManip.h | 4 ++--
src/include/utils/plancache.h | 2 +-
13 files changed, 44 insertions(+), 41 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 43de42ce39e..d4ca965df19 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -3705,7 +3705,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId,
ObjectAddressSet(address, RelationRelationId, indexId);
EventTriggerCollectSimpleCommand(address,
InvalidObjectAddress,
-
(Node *) stmt);
+
(const Node *) stmt);
}
/*
diff --git a/src/backend/commands/event_trigger.c
b/src/backend/commands/event_trigger.c
index 2898967fa67..f9a5aba4360 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -1714,7 +1714,7 @@ EventTriggerUndoInhibitCommandCollection(void)
void
EventTriggerCollectSimpleCommand(ObjectAddress address,
ObjectAddress
secondaryObject,
- Node
*parsetree)
+ const Node
*parsetree)
{
MemoryContext oldcxt;
CollectedCommand *command;
@@ -1750,7 +1750,7 @@ EventTriggerCollectSimpleCommand(ObjectAddress address,
* add it to the command list.
*/
void
-EventTriggerAlterTableStart(Node *parsetree)
+EventTriggerAlterTableStart(const Node *parsetree)
{
MemoryContext oldcxt;
CollectedCommand *command;
@@ -1802,7 +1802,7 @@ EventTriggerAlterTableRelid(Oid objectId)
* internally, so that's all that this code needs to handle at the moment.
*/
void
-EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address)
+EventTriggerCollectAlterTableSubcmd(const Node *subcmd, ObjectAddress address)
{
MemoryContext oldcxt;
CollectedATSubcmd *newsub;
@@ -1919,7 +1919,7 @@ EventTriggerCollectGrant(InternalGrant *istmt)
* executed
*/
void
-EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
+EventTriggerCollectAlterOpFam(const AlterOpFamilyStmt *stmt, Oid opfamoid,
List *operators, List
*procedures)
{
MemoryContext oldcxt;
@@ -1952,7 +1952,7 @@ EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt,
Oid opfamoid,
* Save data about a CREATE OPERATOR CLASS command being executed
*/
void
-EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid,
+EventTriggerCollectCreateOpClass(const CreateOpClassStmt *stmt, Oid opcoid,
List
*operators, List *procedures)
{
MemoryContext oldcxt;
@@ -1986,7 +1986,7 @@ EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt,
Oid opcoid,
* executed
*/
void
-EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId,
+EventTriggerCollectAlterTSConfig(const AlterTSConfigurationStmt *stmt, Oid
cfgId,
Oid *dictIds,
int ndicts)
{
MemoryContext oldcxt;
@@ -2024,7 +2024,7 @@ EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt
*stmt, Oid cfgId,
* executed
*/
void
-EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
+EventTriggerCollectAlterDefPrivs(const AlterDefaultPrivilegesStmt *stmt)
{
MemoryContext oldcxt;
CollectedCommand *command;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 635679cc1f2..6c7f8180bc2 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -543,7 +543,7 @@ WaitForOlderSnapshots(TransactionId limitXmin, bool
progress)
ObjectAddress
DefineIndex(ParseState *pstate,
Oid tableId,
- IndexStmt *stmt,
+ const IndexStmt *stmt,
Oid indexRelationId,
Oid parentIndexId,
Oid parentConstraintId,
@@ -4047,7 +4047,7 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid
relationOid, const Rein
ObjectAddressSet(address, RelationRelationId,
newIndexId);
EventTriggerCollectSimpleCommand(address,
InvalidObjectAddress,
-
(Node *) stmt);
+
(const Node *) stmt);
}
}
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 98d402c0a3b..373a08340fa 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -157,7 +157,7 @@ static HeapTuple check_modified_virtual_generated(TupleDesc
tupdesc, HeapTuple t
* (but see CloneRowTriggersToPartition).
*/
ObjectAddress
-CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
+CreateTrigger(const CreateTrigStmt *stmt, const char *queryString,
Oid relOid, Oid refRelOid, Oid constraintOid, Oid
indexOid,
Oid funcoid, Oid parentTriggerOid, Node *whenClause,
bool isInternal, bool in_partition)
@@ -174,7 +174,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
* (always/origin/replica/disabled) can be specified.
*/
ObjectAddress
-CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
+CreateTriggerFiringOn(const CreateTrigStmt *stmt, const char *queryString,
Oid relOid, Oid refRelOid, Oid
constraintOid,
Oid indexOid, Oid funcoid, Oid
parentTriggerOid,
Node *whenClause, bool isInternal,
bool in_partition,
diff --git a/src/backend/optimizer/prep/prepjointree.c
b/src/backend/optimizer/prep/prepjointree.c
index c90f4b32733..ab621e281e9 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -150,7 +150,7 @@ static void replace_vars_in_jointree(Node *jtnode,
pullup_replace_vars_context *context);
static Node *pullup_replace_vars(Node *expr,
pullup_replace_vars_context *context);
-static Node *pullup_replace_vars_callback(Var *var,
+static Node *pullup_replace_vars_callback(const Var *var,
replace_rte_variables_context *context);
static Query *pullup_replace_vars_subquery(Query *query,
pullup_replace_vars_context *context);
@@ -2698,7 +2698,7 @@ pullup_replace_vars(Node *expr,
pullup_replace_vars_context *context)
}
static Node *
-pullup_replace_vars_callback(Var *var,
+pullup_replace_vars_callback(const Var *var,
replace_rte_variables_context *context)
{
pullup_replace_vars_context *rcon = (pullup_replace_vars_context *)
context->callback_arg;
diff --git a/src/backend/partitioning/partprune.c
b/src/backend/partitioning/partprune.c
index 6d979a08fd3..db1dd153ddb 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -158,7 +158,7 @@ static PartitionPruneStep
*gen_prune_step_combine(GeneratePruningStepsContext *c
static List *gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
List **keyclauses, Bitmapset *nullkeys);
static PartClauseMatchStatus
match_clause_to_partition_key(GeneratePruningStepsContext *context,
-
Expr *clause, Expr *partkey, int partkeyidx,
+
const Expr *clause, const Expr *partkey, int
partkeyidx,
bool *clause_is_not_null,
PartClauseInfo **pc, List **clause_steps);
static List *get_steps_using_prefix(GeneratePruningStepsContext *context,
@@ -196,8 +196,8 @@ static PruneStepResult
*perform_pruning_combine_step(PartitionPruneContext *cont
PartitionPruneStepCombine *cstep,
PruneStepResult **step_results);
static PartClauseMatchStatus match_boolean_partition_clause(Oid partopfamily,
-
Expr *clause,
-
Expr *partkey,
+
const Expr *clause,
+
const Expr *partkey,
Expr **outconst,
bool *notclause);
static void partkey_datum_from_expr(PartitionPruneContext *context,
@@ -1816,7 +1816,7 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext
*context,
*/
static PartClauseMatchStatus
match_clause_to_partition_key(GeneratePruningStepsContext *context,
- Expr *clause, Expr
*partkey, int partkeyidx,
+ const Expr *clause,
const Expr *partkey, int partkeyidx,
bool
*clause_is_not_null, PartClauseInfo **pc,
List **clause_steps)
{
@@ -3697,10 +3697,10 @@ perform_pruning_combine_step(PartitionPruneContext
*context,
* 'partkey'.
*/
static PartClauseMatchStatus
-match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
+match_boolean_partition_clause(Oid partopfamily, const Expr *clause, const
Expr *partkey,
Expr **outconst,
bool *notclause)
{
- Expr *leftop;
+ const Expr *leftop;
*outconst = NULL;
*notclause = false;
diff --git a/src/backend/rewrite/rewriteManip.c
b/src/backend/rewrite/rewriteManip.c
index 6fa174412f2..acd20f61f5a 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1768,7 +1768,7 @@ typedef struct
} ReplaceVarsFromTargetList_context;
static Node *
-ReplaceVarsFromTargetList_callback(Var *var,
+ReplaceVarsFromTargetList_callback(const Var *var,
replace_rte_variables_context *context)
{
ReplaceVarsFromTargetList_context *rcon =
(ReplaceVarsFromTargetList_context *) context->callback_arg;
@@ -1789,7 +1789,7 @@ ReplaceVarsFromTargetList_callback(Var *var,
}
Node *
-ReplaceVarFromTargetList(Var *var,
+ReplaceVarFromTargetList(const Var *var,
RangeTblEntry *target_rte,
List *targetlist,
int result_relation,
@@ -1875,11 +1875,14 @@ ReplaceVarFromTargetList(Var *var,
break;
case REPLACEVARS_CHANGE_VARNO:
- var = copyObject(var);
- var->varno = nomatch_varno;
- var->varlevelsup = 0;
- /* we leave the syntactic referent alone */
- return (Node *) var;
+ {
+ Var *newvar =
copyObject(var);
+
+ newvar->varno = nomatch_varno;
+ newvar->varlevelsup = 0;
+ /* we leave the syntactic referent
alone */
+ return (Node *) newvar;
+ }
case REPLACEVARS_SUBSTITUTE_NULL:
{
diff --git a/src/backend/utils/cache/plancache.c
b/src/backend/utils/cache/plancache.c
index 812e2265734..d67a914d56d 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -182,7 +182,7 @@ InitPlanCache(void)
* commandTag: command tag for query, or UNKNOWN if empty query
*/
CachedPlanSource *
-CreateCachedPlan(RawStmt *raw_parse_tree,
+CreateCachedPlan(const RawStmt *raw_parse_tree,
const char *query_string,
CommandTag commandTag)
{
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 8f4a2d9bbc1..d080ad59b71 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -27,7 +27,7 @@ extern void RemoveObjects(DropStmt *stmt);
/* commands/indexcmds.c */
extern ObjectAddress DefineIndex(ParseState *pstate,
Oid tableId,
- IndexStmt
*stmt,
+ const
IndexStmt *stmt,
Oid
indexRelationId,
Oid
parentIndexId,
Oid
parentConstraintId,
diff --git a/src/include/commands/event_trigger.h
b/src/include/commands/event_trigger.h
index c662782bb1e..27340655061 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -75,23 +75,23 @@ extern void EventTriggerUndoInhibitCommandCollection(void);
extern void EventTriggerCollectSimpleCommand(ObjectAddress address,
ObjectAddress secondaryObject,
-
Node *parsetree);
+
const Node *parsetree);
-extern void EventTriggerAlterTableStart(Node *parsetree);
+extern void EventTriggerAlterTableStart(const Node *parsetree);
extern void EventTriggerAlterTableRelid(Oid objectId);
-extern void EventTriggerCollectAlterTableSubcmd(Node *subcmd,
+extern void EventTriggerCollectAlterTableSubcmd(const Node *subcmd,
ObjectAddress address);
extern void EventTriggerAlterTableEnd(void);
extern void EventTriggerCollectGrant(InternalGrant *istmt);
-extern void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt,
+extern void EventTriggerCollectAlterOpFam(const AlterOpFamilyStmt *stmt,
Oid opfamoid, List *operators,
List *procedures);
-extern void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt,
+extern void EventTriggerCollectCreateOpClass(const CreateOpClassStmt *stmt,
Oid opcoid, List *operators,
List *procedures);
-extern void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt,
+extern void EventTriggerCollectAlterTSConfig(const AlterTSConfigurationStmt
*stmt,
Oid cfgId, Oid *dictIds, int ndicts);
-extern void EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt);
+extern void EventTriggerCollectAlterDefPrivs(const AlterDefaultPrivilegesStmt
*stmt);
#endif /* EVENT_TRIGGER_H */
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
index 556c86bf5e1..27af5284406 100644
--- a/src/include/commands/trigger.h
+++ b/src/include/commands/trigger.h
@@ -153,11 +153,11 @@ extern PGDLLIMPORT int SessionReplicationRole;
#define TRIGGER_FIRES_ON_REPLICA 'R'
#define TRIGGER_DISABLED 'D'
-extern ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char
*queryString,
+extern ObjectAddress CreateTrigger(const CreateTrigStmt *stmt, const char
*queryString,
Oid relOid,
Oid refRelOid, Oid constraintOid, Oid indexOid,
Oid funcoid,
Oid parentTriggerOid, Node *whenClause,
bool
isInternal, bool in_partition);
-extern ObjectAddress CreateTriggerFiringOn(CreateTrigStmt *stmt, const char
*queryString,
+extern ObjectAddress CreateTriggerFiringOn(const CreateTrigStmt *stmt, const
char *queryString,
Oid relOid, Oid refRelOid, Oid constraintOid,
Oid indexOid, Oid funcoid, Oid parentTriggerOid,
Node *whenClause, bool isInternal, bool in_partition,
diff --git a/src/include/rewrite/rewriteManip.h
b/src/include/rewrite/rewriteManip.h
index f8216c22fb7..a6d4e888e06 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.h
@@ -22,7 +22,7 @@ typedef struct AttrMap AttrMap; /* avoid including attmap.h
here */
typedef struct replace_rte_variables_context replace_rte_variables_context;
-typedef Node *(*replace_rte_variables_callback) (Var *var,
+typedef Node *(*replace_rte_variables_callback) (const Var *var,
replace_rte_variables_context *context);
struct replace_rte_variables_context
@@ -104,7 +104,7 @@ extern Node *map_variable_attnos(Node *node,
const AttrMap
*attno_map,
Oid
to_rowtype, bool *found_whole_row);
-extern Node *ReplaceVarFromTargetList(Var *var,
+extern Node *ReplaceVarFromTargetList(const Var *var,
RangeTblEntry *target_rte,
List
*targetlist,
int
result_relation,
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 984c51515c6..7a4a85c8038 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -202,7 +202,7 @@ extern void ResetPlanCache(void);
extern void ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner);
-extern CachedPlanSource *CreateCachedPlan(RawStmt *raw_parse_tree,
+extern CachedPlanSource *CreateCachedPlan(const RawStmt *raw_parse_tree,
const char *query_string,
CommandTag commandTag);
extern CachedPlanSource *CreateCachedPlanForQuery(Query *analyzed_parse_tree,
--
2.53.0