v1-0006-WIP-Datum-as-struct.patch

text/plain

Filename: v1-0006-WIP-Datum-as-struct.patch
Type: text/plain
Part: 5
Message: Datum as struct

Patch

Format: format-patch
Series: patch v1-0006
Subject: WIP: Datum as struct
File+
contrib/btree_gin/btree_gin.c 1 1
contrib/dblink/dblink.c 4 4
contrib/hstore/hstore_io.c 1 1
contrib/hstore/hstore_op.c 4 4
contrib/intarray/_int_bool.c 2 2
contrib/ltree/_ltree_gist.c 1 1
contrib/ltree/ltree_gist.c 1 1
contrib/pageinspect/brinfuncs.c 1 1
contrib/pageinspect/gistfuncs.c 3 3
contrib/pg_buffercache/pg_buffercache_pages.c 1 1
contrib/pg_prewarm/autoprewarm.c 3 3
contrib/pgrowlocks/pgrowlocks.c 1 1
contrib/pg_stat_statements/pg_stat_statements.c 10 10
contrib/pgstattuple/pgstattuple.c 1 1
contrib/postgres_fdw/connection.c 2 2
contrib/postgres_fdw/postgres_fdw.c 1 1
contrib/postgres_fdw/shippable.c 1 1
contrib/seg/seg.c 1 1
contrib/sepgsql/label.c 1 1
contrib/sepgsql/uavc.c 1 1
contrib/spi/moddatetime.c 1 1
contrib/sslinfo/sslinfo.c 3 3
contrib/tablefunc/tablefunc.c 4 4
contrib/xml2/xpath.c 1 1
src/backend/access/brin/brin_bloom.c 2 2
src/backend/access/brin/brin_inclusion.c 2 2
src/backend/access/brin/brin_minmax.c 1 1
src/backend/access/brin/brin_minmax_multi.c 1 1
src/backend/access/common/heaptuple.c 3 3
src/backend/access/common/indextuple.c 1 1
src/backend/access/common/reloptions.c 3 3
src/backend/access/common/tupconvert.c 3 3
src/backend/access/gin/gininsert.c 3 3
src/backend/access/gin/ginscan.c 2 2
src/backend/access/gin/ginutil.c 2 2
src/backend/access/gist/gistproc.c 6 4
src/backend/access/gist/gistutil.c 8 8
src/backend/access/index/indexam.c 2 2
src/backend/access/nbtree/nbtcompare.c 12 12
src/backend/access/nbtree/nbtpreprocesskeys.c 1 1
src/backend/access/nbtree/nbtree.c 6 6
src/backend/access/nbtree/nbtsearch.c 1 1
src/backend/access/nbtree/nbtutils.c 10 10
src/backend/access/spgist/spgdoinsert.c 8 8
src/backend/access/spgist/spgscan.c 6 6
src/backend/access/spgist/spgutils.c 1 1
src/backend/access/transam/rmgr.c 1 1
src/backend/access/transam/twophase.c 2 2
src/backend/access/transam/xlogprefetcher.c 1 1
src/backend/backup/walsummaryfuncs.c 2 2
src/backend/bootstrap/bootparse.y 1 1
src/backend/catalog/aclchk.c 7 7
src/backend/catalog/heap.c 6 6
src/backend/catalog/index.c 6 6
src/backend/catalog/namespace.c 5 5
src/backend/catalog/pg_aggregate.c 1 1
src/backend/catalog/pg_constraint.c 1 1
src/backend/catalog/pg_conversion.c 1 1
src/backend/catalog/pg_namespace.c 1 1
src/backend/catalog/pg_operator.c 2 2
src/backend/catalog/pg_proc.c 9 9
src/backend/catalog/pg_type.c 2 2
src/backend/catalog/toasting.c 3 3
src/backend/commands/analyze.c 3 3
src/backend/commands/async.c 1 1
src/backend/commands/cluster.c 2 2
src/backend/commands/createas.c 1 1
src/backend/commands/event_trigger.c 1 1
src/backend/commands/extension.c 8 8
src/backend/commands/functioncmds.c 2 2
src/backend/commands/indexcmds.c 9 9
src/backend/commands/operatorcmds.c 1 1
src/backend/commands/prepare.c 1 1
src/backend/commands/statscmds.c 2 2
src/backend/commands/tablecmds.c 11 11
src/backend/commands/tablespace.c 4 4
src/backend/commands/trigger.c 1 1
src/backend/commands/tsearchcmds.c 1 1
src/backend/commands/user.c 1 1
src/backend/executor/execExpr.c 3 3
src/backend/executor/execExprInterp.c 34 34
src/backend/executor/execJunk.c 1 1
src/backend/executor/execSRF.c 3 3
src/backend/executor/execTuples.c 4 4
src/backend/executor/execUtils.c 7 7
src/backend/executor/functions.c 6 6
src/backend/executor/nodeAgg.c 12 12
src/backend/executor/nodeFunctionscan.c 1 1
src/backend/executor/nodeIndexscan.c 6 6
src/backend/executor/nodeProjectSet.c 1 1
src/backend/executor/nodeSubplan.c 4 4
src/backend/executor/nodeWindowAgg.c 8 8
src/backend/executor/spi.c 1 1
src/backend/foreign/foreign.c 2 2
src/backend/jit/llvm/llvmjit.c 1 1
src/backend/jit/llvm/llvmjit_expr.c 2 2
src/backend/libpq/pqcomm.c 1 1
src/backend/libpq/pqmq.c 1 1
src/backend/nodes/makefuncs.c 1 1
src/backend/nodes/readfuncs.c 2 2
src/backend/optimizer/prep/prepagg.c 1 1
src/backend/optimizer/prep/preptlist.c 2 2
src/backend/optimizer/util/predtest.c 1 1
src/backend/parser/parse_coerce.c 1 1
src/backend/parser/parse_expr.c 2 2
src/backend/parser/parse_node.c 1 1
src/backend/parser/parse_oper.c 2 2
src/backend/parser/parse_utilcmd.c 1 1
src/backend/partitioning/partbounds.c 2 2
src/backend/port/posix_sema.c 1 1
src/backend/port/sysv_sema.c 1 1
src/backend/port/sysv_shmem.c 1 1
src/backend/port/win32_sema.c 1 1
src/backend/postmaster/autovacuum.c 1 1
src/backend/postmaster/auxprocess.c 1 1
src/backend/postmaster/checkpointer.c 2 2
src/backend/postmaster/pgarch.c 2 2
src/backend/postmaster/postmaster.c 2 2
src/backend/postmaster/startup.c 1 1
src/backend/postmaster/walsummarizer.c 1 1
src/backend/replication/logical/applyparallelworker.c 1 1
src/backend/replication/logical/launcher.c 4 4
src/backend/replication/logical/logicalfuncs.c 1 1
src/backend/replication/logical/origin.c 2 2
src/backend/replication/logical/relation.c 2 2
src/backend/replication/logical/slotsync.c 1 1
src/backend/replication/logical/worker.c 8 8
src/backend/replication/pgoutput/pgoutput.c 5 5
src/backend/replication/slot.c 1 1
src/backend/replication/slotfuncs.c 1 1
src/backend/replication/walsender.c 2 2
src/backend/statistics/attribute_stats.c 7 7
src/backend/statistics/extended_stats.c 7 7
src/backend/statistics/mcv.c 2 2
src/backend/statistics/stat_utils.c 1 1
src/backend/storage/aio/aio_funcs.c 1 1
src/backend/storage/aio/aio_init.c 1 1
src/backend/storage/aio/method_worker.c 1 1
src/backend/storage/buffer/bufmgr.c 1 1
src/backend/storage/file/fd.c 1 1
src/backend/storage/ipc/dsm.c 1 1
src/backend/storage/ipc/dsm_registry.c 1 1
src/backend/storage/ipc/ipc.c 2 2
src/backend/storage/ipc/pmsignal.c 1 1
src/backend/storage/ipc/procsignal.c 1 1
src/backend/storage/ipc/shmem.c 2 2
src/backend/storage/lmgr/predicate.c 13 5
src/backend/storage/lmgr/proc.c 2 2
src/backend/storage/smgr/smgr.c 1 1
src/backend/tcop/fastpath.c 1 1
src/backend/tcop/postgres.c 2 2
src/backend/tcop/utility.c 1 1
src/backend/tsearch/ts_typanalyze.c 1 1
src/backend/tsearch/wparser.c 11 7
src/backend/utils/activity/backend_status.c 1 1
src/backend/utils/activity/pgstat.c 1 1
src/backend/utils/activity/pgstat_shmem.c 2 2
src/backend/utils/activity/wait_event_funcs.c 1 1
src/backend/utils/adt/acl.c 4 4
src/backend/utils/adt/arrayfuncs.c 21 21
src/backend/utils/adt/array_selfuncs.c 1 1
src/backend/utils/adt/arraysubs.c 2 2
src/backend/utils/adt/array_typanalyze.c 1 1
src/backend/utils/adt/array_userfuncs.c 9 9
src/backend/utils/adt/bool.c 1 1
src/backend/utils/adt/bytea.c 1 1
src/backend/utils/adt/cash.c 5 5
src/backend/utils/adt/date.c 4 4
src/backend/utils/adt/datetime.c 1 1
src/backend/utils/adt/datum.c 3 3
src/backend/utils/adt/enum.c 2 2
src/backend/utils/adt/expandedrecord.c 4 4
src/backend/utils/adt/formatting.c 11 11
src/backend/utils/adt/genfile.c 4 4
src/backend/utils/adt/geo_ops.c 11 11
src/backend/utils/adt/int.c 3 3
src/backend/utils/adt/jsonb.c 3 3
src/backend/utils/adt/jsonb_gin.c 1 1
src/backend/utils/adt/jsonbsubs.c 1 1
src/backend/utils/adt/json.c 2 2
src/backend/utils/adt/jsonfuncs.c 19 19
src/backend/utils/adt/jsonpath.c 3 3
src/backend/utils/adt/jsonpath_exec.c 3 3
src/backend/utils/adt/mac8.c 1 1
src/backend/utils/adt/mac.c 5 5
src/backend/utils/adt/mcxtfuncs.c 1 1
src/backend/utils/adt/misc.c 3 3
src/backend/utils/adt/multirangetypes.c 7 7
src/backend/utils/adt/network.c 19 19
src/backend/utils/adt/network_gist.c 1 1
src/backend/utils/adt/numeric.c 6 6
src/backend/utils/adt/orderedsetaggs.c 13 13
src/backend/utils/adt/pg_lsn.c 1 1
src/backend/utils/adt/pgstatfuncs.c 6 6
src/backend/utils/adt/rangetypes.c 18 18
src/backend/utils/adt/regexp.c 1 1
src/backend/utils/adt/regproc.c 18 18
src/backend/utils/adt/ri_triggers.c 1 1
src/backend/utils/adt/rowtypes.c 5 5
src/backend/utils/adt/ruleutils.c 1 1
src/backend/utils/adt/selfuncs.c 3 3
src/backend/utils/adt/tid.c 4 4
src/backend/utils/adt/timestamp.c 5 5
src/backend/utils/adt/tsvector.c 3 3
src/backend/utils/adt/tsvector_op.c 5 3
src/backend/utils/adt/uuid.c 5 5
src/backend/utils/adt/varbit.c 8 8
src/backend/utils/adt/varlena.c 11 11
src/backend/utils/adt/xml.c 13 13
src/backend/utils/cache/attoptcache.c 1 1
src/backend/utils/cache/catcache.c 8 8
src/backend/utils/cache/evtcache.c 1 1
src/backend/utils/cache/lsyscache.c 1 1
src/backend/utils/cache/plancache.c 8 8
src/backend/utils/cache/relcache.c 2 2
src/backend/utils/cache/relfilenumbermap.c 1 1
src/backend/utils/cache/spccache.c 1 1
src/backend/utils/cache/typcache.c 5 5
src/backend/utils/fmgr/fmgr.c 4 4
src/backend/utils/fmgr/funcapi.c 6 6
src/backend/utils/init/miscinit.c 1 1
src/backend/utils/init/postinit.c 3 3
src/backend/utils/misc/guc_funcs.c 1 1
src/backend/utils/misc/pg_config.c 1 1
src/backend/utils/misc/superuser.c 1 1
src/backend/utils/mmgr/portalmem.c 1 1
src/backend/utils/resowner/resowner.c 7 7
src/backend/utils/sort/tuplesort.c 2 2
src/backend/utils/sort/tuplesortvariants.c 4 4
src/include/access/gin.h 2 2
src/include/access/htup_details.h 1 1
src/include/access/itup.h 1 1
src/include/access/spgist_private.h 1 1
src/include/access/tupmacs.h 1 1
src/include/executor/executor.h 1 1
src/include/fmgr.h 4 2
src/include/nodes/nodes.h 4 2
src/include/port/pg_bswap.h 3 3
src/include/postgres.h 32 29
src/include/utils/arrayaccess.h 1 1
src/include/utils/sortsupport.h 1 1
src/include/utils/syscache.h 14 14
src/pl/plperl/plperl.c 6 6
src/pl/plpgsql/src/pl_comp.c 1 1
src/pl/plpgsql/src/pl_exec.c 20 20
src/pl/plpgsql/src/pl_handler.c 1 1
src/pl/plpython/plpy_exec.c 2 2
src/pl/plpython/plpy_typeio.c 10 10
src/pl/tcl/pltcl.c 3 3
src/test/modules/injection_points/injection_points.c 2 2
src/test/modules/injection_points/injection_stats.c 1 1
src/test/modules/plsample/plsample.c 1 1
src/test/modules/test_ddl_deparse/test_ddl_deparse.c 1 1
src/test/modules/test_regex/test_regex.c 1 1
From 81e56922fe429fae6ebc33b2f518ef88b00ffc42 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 31 Jul 2025 15:18:02 +0200
Subject: [PATCH v1 6/6] WIP: Datum as struct

This changes Datum to a struct so that you can no longer rely on it
being implicitly convertable to other C types.
---
 contrib/btree_gin/btree_gin.c                 |  2 +-
 contrib/dblink/dblink.c                       |  8 +--
 contrib/hstore/hstore_io.c                    |  2 +-
 contrib/hstore/hstore_op.c                    |  8 +--
 contrib/intarray/_int_bool.c                  |  4 +-
 contrib/ltree/_ltree_gist.c                   |  2 +-
 contrib/ltree/ltree_gist.c                    |  2 +-
 contrib/pageinspect/brinfuncs.c               |  2 +-
 contrib/pageinspect/gistfuncs.c               |  6 +-
 contrib/pg_buffercache/pg_buffercache_pages.c |  2 +-
 contrib/pg_prewarm/autoprewarm.c              |  6 +-
 .../pg_stat_statements/pg_stat_statements.c   | 20 +++---
 contrib/pgrowlocks/pgrowlocks.c               |  2 +-
 contrib/pgstattuple/pgstattuple.c             |  2 +-
 contrib/postgres_fdw/connection.c             |  4 +-
 contrib/postgres_fdw/postgres_fdw.c           |  2 +-
 contrib/postgres_fdw/shippable.c              |  2 +-
 contrib/seg/seg.c                             |  2 +-
 contrib/sepgsql/label.c                       |  2 +-
 contrib/sepgsql/uavc.c                        |  2 +-
 contrib/spi/moddatetime.c                     |  2 +-
 contrib/sslinfo/sslinfo.c                     |  6 +-
 contrib/tablefunc/tablefunc.c                 |  8 +--
 contrib/xml2/xpath.c                          |  2 +-
 src/backend/access/brin/brin_bloom.c          |  4 +-
 src/backend/access/brin/brin_inclusion.c      |  4 +-
 src/backend/access/brin/brin_minmax.c         |  2 +-
 src/backend/access/brin/brin_minmax_multi.c   |  2 +-
 src/backend/access/common/heaptuple.c         |  6 +-
 src/backend/access/common/indextuple.c        |  2 +-
 src/backend/access/common/reloptions.c        |  6 +-
 src/backend/access/common/tupconvert.c        |  6 +-
 src/backend/access/gin/gininsert.c            |  6 +-
 src/backend/access/gin/ginscan.c              |  4 +-
 src/backend/access/gin/ginutil.c              |  4 +-
 src/backend/access/gist/gistproc.c            | 10 +--
 src/backend/access/gist/gistutil.c            | 16 ++---
 src/backend/access/index/indexam.c            |  4 +-
 src/backend/access/nbtree/nbtcompare.c        | 24 +++----
 src/backend/access/nbtree/nbtpreprocesskeys.c |  2 +-
 src/backend/access/nbtree/nbtree.c            | 12 ++--
 src/backend/access/nbtree/nbtsearch.c         |  2 +-
 src/backend/access/nbtree/nbtutils.c          | 20 +++---
 src/backend/access/spgist/spgdoinsert.c       | 16 ++---
 src/backend/access/spgist/spgscan.c           | 12 ++--
 src/backend/access/spgist/spgutils.c          |  2 +-
 src/backend/access/transam/rmgr.c             |  2 +-
 src/backend/access/transam/twophase.c         |  4 +-
 src/backend/access/transam/xlogprefetcher.c   |  2 +-
 src/backend/backup/walsummaryfuncs.c          |  4 +-
 src/backend/bootstrap/bootparse.y             |  2 +-
 src/backend/catalog/aclchk.c                  | 14 ++--
 src/backend/catalog/heap.c                    | 12 ++--
 src/backend/catalog/index.c                   | 12 ++--
 src/backend/catalog/namespace.c               | 10 +--
 src/backend/catalog/pg_aggregate.c            |  2 +-
 src/backend/catalog/pg_constraint.c           |  2 +-
 src/backend/catalog/pg_conversion.c           |  2 +-
 src/backend/catalog/pg_namespace.c            |  2 +-
 src/backend/catalog/pg_operator.c             |  4 +-
 src/backend/catalog/pg_proc.c                 | 18 ++---
 src/backend/catalog/pg_type.c                 |  4 +-
 src/backend/catalog/toasting.c                |  6 +-
 src/backend/commands/analyze.c                |  6 +-
 src/backend/commands/async.c                  |  2 +-
 src/backend/commands/cluster.c                |  4 +-
 src/backend/commands/createas.c               |  2 +-
 src/backend/commands/event_trigger.c          |  2 +-
 src/backend/commands/extension.c              | 16 ++---
 src/backend/commands/functioncmds.c           |  4 +-
 src/backend/commands/indexcmds.c              | 18 ++---
 src/backend/commands/operatorcmds.c           |  2 +-
 src/backend/commands/prepare.c                |  2 +-
 src/backend/commands/statscmds.c              |  4 +-
 src/backend/commands/tablecmds.c              | 22 +++---
 src/backend/commands/tablespace.c             |  8 +--
 src/backend/commands/trigger.c                |  2 +-
 src/backend/commands/tsearchcmds.c            |  2 +-
 src/backend/commands/user.c                   |  2 +-
 src/backend/executor/execExpr.c               |  6 +-
 src/backend/executor/execExprInterp.c         | 68 +++++++++----------
 src/backend/executor/execJunk.c               |  2 +-
 src/backend/executor/execSRF.c                |  6 +-
 src/backend/executor/execTuples.c             |  8 +--
 src/backend/executor/execUtils.c              | 14 ++--
 src/backend/executor/functions.c              | 12 ++--
 src/backend/executor/nodeAgg.c                | 24 +++----
 src/backend/executor/nodeFunctionscan.c       |  2 +-
 src/backend/executor/nodeIndexscan.c          | 12 ++--
 src/backend/executor/nodeProjectSet.c         |  2 +-
 src/backend/executor/nodeSubplan.c            |  8 +--
 src/backend/executor/nodeWindowAgg.c          | 16 ++---
 src/backend/executor/spi.c                    |  2 +-
 src/backend/foreign/foreign.c                 |  4 +-
 src/backend/jit/llvm/llvmjit.c                |  2 +-
 src/backend/jit/llvm/llvmjit_expr.c           |  4 +-
 src/backend/libpq/pqcomm.c                    |  2 +-
 src/backend/libpq/pqmq.c                      |  2 +-
 src/backend/nodes/makefuncs.c                 |  2 +-
 src/backend/nodes/readfuncs.c                 |  4 +-
 src/backend/optimizer/prep/prepagg.c          |  2 +-
 src/backend/optimizer/prep/preptlist.c        |  4 +-
 src/backend/optimizer/util/predtest.c         |  2 +-
 src/backend/parser/parse_coerce.c             |  2 +-
 src/backend/parser/parse_expr.c               |  4 +-
 src/backend/parser/parse_node.c               |  2 +-
 src/backend/parser/parse_oper.c               |  4 +-
 src/backend/parser/parse_utilcmd.c            |  2 +-
 src/backend/partitioning/partbounds.c         |  4 +-
 src/backend/port/posix_sema.c                 |  2 +-
 src/backend/port/sysv_sema.c                  |  2 +-
 src/backend/port/sysv_shmem.c                 |  2 +-
 src/backend/port/win32_sema.c                 |  2 +-
 src/backend/postmaster/autovacuum.c           |  2 +-
 src/backend/postmaster/auxprocess.c           |  2 +-
 src/backend/postmaster/checkpointer.c         |  4 +-
 src/backend/postmaster/pgarch.c               |  4 +-
 src/backend/postmaster/postmaster.c           |  4 +-
 src/backend/postmaster/startup.c              |  2 +-
 src/backend/postmaster/walsummarizer.c        |  2 +-
 .../replication/logical/applyparallelworker.c |  2 +-
 src/backend/replication/logical/launcher.c    |  8 +--
 .../replication/logical/logicalfuncs.c        |  2 +-
 src/backend/replication/logical/origin.c      |  4 +-
 src/backend/replication/logical/relation.c    |  4 +-
 src/backend/replication/logical/slotsync.c    |  2 +-
 src/backend/replication/logical/worker.c      | 16 ++---
 src/backend/replication/pgoutput/pgoutput.c   | 10 +--
 src/backend/replication/slot.c                |  2 +-
 src/backend/replication/slotfuncs.c           |  2 +-
 src/backend/replication/walsender.c           |  4 +-
 src/backend/statistics/attribute_stats.c      | 14 ++--
 src/backend/statistics/extended_stats.c       | 14 ++--
 src/backend/statistics/mcv.c                  |  4 +-
 src/backend/statistics/stat_utils.c           |  2 +-
 src/backend/storage/aio/aio_funcs.c           |  2 +-
 src/backend/storage/aio/aio_init.c            |  2 +-
 src/backend/storage/aio/method_worker.c       |  2 +-
 src/backend/storage/buffer/bufmgr.c           |  2 +-
 src/backend/storage/file/fd.c                 |  2 +-
 src/backend/storage/ipc/dsm.c                 |  2 +-
 src/backend/storage/ipc/dsm_registry.c        |  2 +-
 src/backend/storage/ipc/ipc.c                 |  4 +-
 src/backend/storage/ipc/pmsignal.c            |  2 +-
 src/backend/storage/ipc/procsignal.c          |  2 +-
 src/backend/storage/ipc/shmem.c               |  4 +-
 src/backend/storage/lmgr/predicate.c          | 18 +++--
 src/backend/storage/lmgr/proc.c               |  4 +-
 src/backend/storage/smgr/smgr.c               |  2 +-
 src/backend/tcop/fastpath.c                   |  2 +-
 src/backend/tcop/postgres.c                   |  4 +-
 src/backend/tcop/utility.c                    |  2 +-
 src/backend/tsearch/ts_typanalyze.c           |  2 +-
 src/backend/tsearch/wparser.c                 | 18 +++--
 src/backend/utils/activity/backend_status.c   |  2 +-
 src/backend/utils/activity/pgstat.c           |  2 +-
 src/backend/utils/activity/pgstat_shmem.c     |  4 +-
 src/backend/utils/activity/wait_event_funcs.c |  2 +-
 src/backend/utils/adt/acl.c                   |  8 +--
 src/backend/utils/adt/array_selfuncs.c        |  2 +-
 src/backend/utils/adt/array_typanalyze.c      |  2 +-
 src/backend/utils/adt/array_userfuncs.c       | 18 ++---
 src/backend/utils/adt/arrayfuncs.c            | 42 ++++++------
 src/backend/utils/adt/arraysubs.c             |  4 +-
 src/backend/utils/adt/bool.c                  |  2 +-
 src/backend/utils/adt/bytea.c                 |  2 +-
 src/backend/utils/adt/cash.c                  | 10 +--
 src/backend/utils/adt/date.c                  |  8 +--
 src/backend/utils/adt/datetime.c              |  2 +-
 src/backend/utils/adt/datum.c                 |  6 +-
 src/backend/utils/adt/enum.c                  |  4 +-
 src/backend/utils/adt/expandedrecord.c        |  8 +--
 src/backend/utils/adt/formatting.c            | 22 +++---
 src/backend/utils/adt/genfile.c               |  8 +--
 src/backend/utils/adt/geo_ops.c               | 22 +++---
 src/backend/utils/adt/int.c                   |  6 +-
 src/backend/utils/adt/json.c                  |  4 +-
 src/backend/utils/adt/jsonb.c                 |  6 +-
 src/backend/utils/adt/jsonb_gin.c             |  2 +-
 src/backend/utils/adt/jsonbsubs.c             |  2 +-
 src/backend/utils/adt/jsonfuncs.c             | 38 +++++------
 src/backend/utils/adt/jsonpath.c              |  6 +-
 src/backend/utils/adt/jsonpath_exec.c         |  6 +-
 src/backend/utils/adt/mac.c                   | 10 +--
 src/backend/utils/adt/mac8.c                  |  2 +-
 src/backend/utils/adt/mcxtfuncs.c             |  2 +-
 src/backend/utils/adt/misc.c                  |  6 +-
 src/backend/utils/adt/multirangetypes.c       | 14 ++--
 src/backend/utils/adt/network.c               | 38 +++++------
 src/backend/utils/adt/network_gist.c          |  2 +-
 src/backend/utils/adt/numeric.c               | 12 ++--
 src/backend/utils/adt/orderedsetaggs.c        | 26 +++----
 src/backend/utils/adt/pg_lsn.c                |  2 +-
 src/backend/utils/adt/pgstatfuncs.c           | 12 ++--
 src/backend/utils/adt/rangetypes.c            | 36 +++++-----
 src/backend/utils/adt/regexp.c                |  2 +-
 src/backend/utils/adt/regproc.c               | 36 +++++-----
 src/backend/utils/adt/ri_triggers.c           |  2 +-
 src/backend/utils/adt/rowtypes.c              | 10 +--
 src/backend/utils/adt/ruleutils.c             |  2 +-
 src/backend/utils/adt/selfuncs.c              |  6 +-
 src/backend/utils/adt/tid.c                   |  8 +--
 src/backend/utils/adt/timestamp.c             | 10 +--
 src/backend/utils/adt/tsvector.c              |  6 +-
 src/backend/utils/adt/tsvector_op.c           |  8 ++-
 src/backend/utils/adt/uuid.c                  | 10 +--
 src/backend/utils/adt/varbit.c                | 16 ++---
 src/backend/utils/adt/varlena.c               | 22 +++---
 src/backend/utils/adt/xml.c                   | 26 +++----
 src/backend/utils/cache/attoptcache.c         |  2 +-
 src/backend/utils/cache/catcache.c            | 16 ++---
 src/backend/utils/cache/evtcache.c            |  2 +-
 src/backend/utils/cache/lsyscache.c           |  2 +-
 src/backend/utils/cache/plancache.c           | 16 ++---
 src/backend/utils/cache/relcache.c            |  4 +-
 src/backend/utils/cache/relfilenumbermap.c    |  2 +-
 src/backend/utils/cache/spccache.c            |  2 +-
 src/backend/utils/cache/typcache.c            | 10 +--
 src/backend/utils/fmgr/fmgr.c                 |  8 +--
 src/backend/utils/fmgr/funcapi.c              | 12 ++--
 src/backend/utils/init/miscinit.c             |  2 +-
 src/backend/utils/init/postinit.c             |  6 +-
 src/backend/utils/misc/guc_funcs.c            |  2 +-
 src/backend/utils/misc/pg_config.c            |  2 +-
 src/backend/utils/misc/superuser.c            |  2 +-
 src/backend/utils/mmgr/portalmem.c            |  2 +-
 src/backend/utils/resowner/resowner.c         | 14 ++--
 src/backend/utils/sort/tuplesort.c            |  4 +-
 src/backend/utils/sort/tuplesortvariants.c    |  8 +--
 src/include/access/gin.h                      |  4 +-
 src/include/access/htup_details.h             |  2 +-
 src/include/access/itup.h                     |  2 +-
 src/include/access/spgist_private.h           |  2 +-
 src/include/access/tupmacs.h                  |  2 +-
 src/include/executor/executor.h               |  2 +-
 src/include/fmgr.h                            |  6 +-
 src/include/nodes/nodes.h                     |  6 +-
 src/include/port/pg_bswap.h                   |  6 +-
 src/include/postgres.h                        | 61 +++++++++--------
 src/include/utils/arrayaccess.h               |  2 +-
 src/include/utils/sortsupport.h               |  2 +-
 src/include/utils/syscache.h                  | 28 ++++----
 src/pl/plperl/plperl.c                        | 12 ++--
 src/pl/plpgsql/src/pl_comp.c                  |  2 +-
 src/pl/plpgsql/src/pl_exec.c                  | 40 +++++------
 src/pl/plpgsql/src/pl_handler.c               |  2 +-
 src/pl/plpython/plpy_exec.c                   |  4 +-
 src/pl/plpython/plpy_typeio.c                 | 20 +++---
 src/pl/tcl/pltcl.c                            |  6 +-
 .../injection_points/injection_points.c       |  4 +-
 .../injection_points/injection_stats.c        |  2 +-
 src/test/modules/plsample/plsample.c          |  2 +-
 .../test_ddl_deparse/test_ddl_deparse.c       |  2 +-
 src/test/modules/test_regex/test_regex.c      |  2 +-
 254 files changed, 915 insertions(+), 892 deletions(-)

diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index 8c477d17e22..5125232376e 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -166,7 +166,7 @@ gin_btree_compare_prefix(FunctionCallInfo fcinfo)
 	 * we'll notice if anyone ever changes the core code in a way that breaks
 	 * our assumptions.
 	 */
-	Assert(partial_key == data->entry_datum);
+	Assert(partial_key.value == data->entry_datum.value);
 
 	cmp = DatumGetInt32(CallerFInfoFunctionCall2(data->typecmp,
 												 fcinfo->flinfo,
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index f98805fb5f7..e56e0db97c9 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -653,7 +653,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
 	{
 		dblink_res_error(conn, conname, res, fail,
 						 "while fetching from cursor \"%s\"", curname);
-		return (Datum) 0;
+		PG_RETURN_DUMMY();
 	}
 	else if (PQresultStatus(res) == PGRES_COMMAND_OK)
 	{
@@ -665,7 +665,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
 	}
 
 	materializeResult(fcinfo, conn, res);
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
@@ -821,7 +821,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async)
 	}
 	PG_END_TRY();
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
@@ -1915,7 +1915,7 @@ dblink_get_notify(PG_FUNCTION_ARGS)
 		PQconsumeInput(conn);
 	}
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 9c53877c4a5..d059b31231f 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -1113,7 +1113,7 @@ hstore_populate_record(PG_FUNCTION_ARGS)
 	{
 		for (i = 0; i < ncolumns; ++i)
 		{
-			values[i] = (Datum) 0;
+			values[i] = DummyDatum;
 			nulls[i] = true;
 		}
 	}
diff --git a/contrib/hstore/hstore_op.c b/contrib/hstore/hstore_op.c
index bcba75f9258..b22c4b32827 100644
--- a/contrib/hstore/hstore_op.c
+++ b/contrib/hstore/hstore_op.c
@@ -604,7 +604,7 @@ hstore_slice_to_array(PG_FUNCTION_ARGS)
 		if (idx < 0 || HSTORE_VALISNULL(entries, idx))
 		{
 			out_nulls[i] = true;
-			out_datums[i] = (Datum) 0;
+			out_datums[i] = DummyDatum;
 		}
 		else
 		{
@@ -748,7 +748,7 @@ hstore_avals(PG_FUNCTION_ARGS)
 	{
 		if (HSTORE_VALISNULL(entries, i))
 		{
-			d[i] = (Datum) 0;
+			d[i] = DummyDatum;
 			nulls[i] = true;
 		}
 		else
@@ -799,7 +799,7 @@ hstore_to_array_internal(HStore *hs, int ndims)
 
 		if (HSTORE_VALISNULL(entries, i))
 		{
-			out_datums[i * 2 + 1] = (Datum) 0;
+			out_datums[i * 2 + 1] = DummyDatum;
 			out_nulls[i * 2 + 1] = true;
 		}
 		else
@@ -1051,7 +1051,7 @@ hstore_each(PG_FUNCTION_ARGS)
 
 		if (HSTORE_VALISNULL(entries, i))
 		{
-			dvalues[1] = (Datum) 0;
+			dvalues[1] = DummyDatum;
 			nulls[1] = true;
 		}
 		else
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 2b2c3f4029e..0ee6ea7d5c5 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -499,12 +499,12 @@ bqarr_in(PG_FUNCTION_ARGS)
 	if (makepol(&state) == ERR)
 		PG_RETURN_NULL();
 	if (!state.num)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("empty query")));
 
 	if (state.num > QUERYTYPEMAXITEMS)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
 						state.num, (int) QUERYTYPEMAXITEMS)));
diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c
index 286ad24fbe8..2d71cea7e5a 100644
--- a/contrib/ltree/_ltree_gist.c
+++ b/contrib/ltree/_ltree_gist.c
@@ -84,7 +84,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
 					  entry->rel, entry->page,
 					  entry->offset, false);
 	}
-	else if (!LTG_ISALLTRUE(entry->key))
+	else if (!LTG_ISALLTRUE(entry->key.value))
 	{
 		int32		i;
 		ltree_gist *key;
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index 932f69bff2d..49bf8e32593 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -115,7 +115,7 @@ ltree_decompress(PG_FUNCTION_ARGS)
 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 	ltree_gist *key = (ltree_gist *) PG_DETOAST_DATUM(entry->key);
 
-	if (PointerGetDatum(key) != entry->key)
+	if (PointerGetDatum(key).value != entry->key.value)
 	{
 		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
 
diff --git a/contrib/pageinspect/brinfuncs.c b/contrib/pageinspect/brinfuncs.c
index 990c965aa92..458e8bcf3ff 100644
--- a/contrib/pageinspect/brinfuncs.c
+++ b/contrib/pageinspect/brinfuncs.c
@@ -336,7 +336,7 @@ brin_page_items(PG_FUNCTION_ARGS)
 	brin_free_desc(bdesc);
 	index_close(indexRel, AccessShareLock);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c
index 1b299374890..2396101342a 100644
--- a/contrib/pageinspect/gistfuncs.c
+++ b/contrib/pageinspect/gistfuncs.c
@@ -187,7 +187,7 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -353,7 +353,7 @@ gist_page_items(PG_FUNCTION_ARGS)
 		}
 		else
 		{
-			values[4] = (Datum) 0;
+			//values[4] = DummyDatum;
 			nulls[4] = true;
 		}
 
@@ -362,5 +362,5 @@ gist_page_items(PG_FUNCTION_ARGS)
 
 	relation_close(indexRel, AccessShareLock);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index ae0291e6e96..6450f122b72 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -640,7 +640,7 @@ pg_buffercache_usage_counts(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index c01b9c7e6a4..2f611a0971c 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -187,7 +187,7 @@ autoprewarm_main(Datum main_arg)
 	 * are detached before calling the on_shmem_exit callbacks, so we must put
 	 * apw_detach_shmem in the before_shmem_exit callback list.
 	 */
-	before_shmem_exit(apw_detach_shmem, 0);
+	before_shmem_exit(apw_detach_shmem, DummyDatum);
 
 	/*
 	 * Store our PID in the shared memory area --- unless there's already
@@ -850,11 +850,11 @@ autoprewarm_dump_now(PG_FUNCTION_ARGS)
 
 	apw_init_shmem();
 
-	PG_ENSURE_ERROR_CLEANUP(apw_detach_shmem, 0);
+	PG_ENSURE_ERROR_CLEANUP(apw_detach_shmem, DummyDatum);
 	{
 		num_blocks = apw_dump_now(false, true);
 	}
-	PG_END_ENSURE_ERROR_CLEANUP(apw_detach_shmem, 0);
+	PG_END_ENSURE_ERROR_CLEANUP(apw_detach_shmem, DummyDatum);
 
 	PG_RETURN_INT64((int64) num_blocks);
 }
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 9fc9635d330..1fe8807319c 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -570,7 +570,7 @@ pgss_shmem_startup(void)
 	 * exit hook to dump the statistics to disk.
 	 */
 	if (!IsUnderPostmaster)
-		on_shmem_exit(pgss_shmem_shutdown, (Datum) 0);
+		on_shmem_exit(pgss_shmem_shutdown, DummyDatum);
 
 	/*
 	 * Done if some other process already completed our initialization.
@@ -1598,7 +1598,7 @@ pg_stat_statements_1_13(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_13, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -1608,7 +1608,7 @@ pg_stat_statements_1_12(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_12, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -1618,7 +1618,7 @@ pg_stat_statements_1_11(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_11, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -1628,7 +1628,7 @@ pg_stat_statements_1_10(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_10, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -1638,7 +1638,7 @@ pg_stat_statements_1_9(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_9, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -1648,7 +1648,7 @@ pg_stat_statements_1_8(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_8, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -1658,7 +1658,7 @@ pg_stat_statements_1_3(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_3, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 Datum
@@ -1668,7 +1668,7 @@ pg_stat_statements_1_2(PG_FUNCTION_ARGS)
 
 	pg_stat_statements_internal(fcinfo, PGSS_V1_2, showtext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
@@ -1681,7 +1681,7 @@ pg_stat_statements(PG_FUNCTION_ARGS)
 	/* If it's really API 1.1, we'll figure that out below */
 	pg_stat_statements_internal(fcinfo, PGSS_V1_0, true);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /* Common code for all versions of pg_stat_statements() */
diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c
index f88269332b6..e11d9c610a6 100644
--- a/contrib/pgrowlocks/pgrowlocks.c
+++ b/contrib/pgrowlocks/pgrowlocks.c
@@ -275,5 +275,5 @@ pgrowlocks(PG_FUNCTION_ARGS)
 
 	table_endscan(scan);
 	table_close(rel, AccessShareLock);
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 0d9c2b0b653..267cc2ce7ae 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -306,7 +306,7 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
 				 errdetail_relkind_not_supported(rel->rd_rel->relkind)));
 	}
 
-	return 0;					/* should not happen */
+	return DummyDatum;					/* should not happen */
 }
 
 /*
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index e8148f2c5a2..06ef45a0958 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -232,9 +232,9 @@ GetConnection(UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
 		RegisterXactCallback(pgfdw_xact_callback, NULL);
 		RegisterSubXactCallback(pgfdw_subxact_callback, NULL);
 		CacheRegisterSyscacheCallback(FOREIGNSERVEROID,
-									  pgfdw_inval_callback, (Datum) 0);
+									  pgfdw_inval_callback, DummyDatum);
 		CacheRegisterSyscacheCallback(USERMAPPINGOID,
-									  pgfdw_inval_callback, (Datum) 0);
+									  pgfdw_inval_callback, DummyDatum);
 	}
 
 	/* Set flag that we did GetConnection during the current transaction */
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 456b267f70b..d517a60a206 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -4743,7 +4743,7 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate,
 
 		if (j == 0)
 		{
-			values[i] = (Datum) 0;
+			//values[i] = DummyDatum;
 			isnull[i] = true;
 		}
 		else
diff --git a/contrib/postgres_fdw/shippable.c b/contrib/postgres_fdw/shippable.c
index da3b13b207d..dbe3ac3a32d 100644
--- a/contrib/postgres_fdw/shippable.c
+++ b/contrib/postgres_fdw/shippable.c
@@ -101,7 +101,7 @@ InitializeShippableCache(void)
 	/* Set up invalidation callback on pg_foreign_server. */
 	CacheRegisterSyscacheCallback(FOREIGNSERVEROID,
 								  InvalidateShippableCacheCallback,
-								  (Datum) 0);
+								  DummyDatum);
 }
 
 /*
diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c
index b5de2a5e1be..74e65fcbcf6 100644
--- a/contrib/seg/seg.c
+++ b/contrib/seg/seg.c
@@ -230,7 +230,7 @@ gseg_union(PG_FUNCTION_ARGS)
 	int		   *sizep = (int *) PG_GETARG_POINTER(1);
 	int			numranges,
 				i;
-	Datum		out = 0;
+	Datum		out = DummyDatum;
 	Datum		tmp;
 
 #ifdef GIST_DEBUG
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
index 996ce174454..5d57563ecb7 100644
--- a/contrib/sepgsql/label.c
+++ b/contrib/sepgsql/label.c
@@ -330,7 +330,7 @@ sepgsql_fmgr_hook(FmgrHookEventType event,
 				stack = palloc(sizeof(*stack));
 				stack->old_label = NULL;
 				stack->new_label = sepgsql_avc_trusted_proc(flinfo->fn_oid);
-				stack->next_private = 0;
+				stack->next_private.value = 0;
 
 				MemoryContextSwitchTo(oldcxt);
 
diff --git a/contrib/sepgsql/uavc.c b/contrib/sepgsql/uavc.c
index d9ccbc38bc5..02472e3bdfe 100644
--- a/contrib/sepgsql/uavc.c
+++ b/contrib/sepgsql/uavc.c
@@ -517,5 +517,5 @@ sepgsql_avc_init(void)
 				(errmsg("SELinux: kernel status page uses fallback mode")));
 
 	/* Arrange to close selinux status page on process exit. */
-	on_proc_exit(sepgsql_avc_exit, 0);
+	on_proc_exit(sepgsql_avc_exit, DummyDatum);
 }
diff --git a/contrib/spi/moddatetime.c b/contrib/spi/moddatetime.c
index 5013eee433e..511402d26e8 100644
--- a/contrib/spi/moddatetime.c
+++ b/contrib/spi/moddatetime.c
@@ -118,7 +118,7 @@ moddatetime(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
 				 errmsg("attribute \"%s\" of \"%s\" must be type TIMESTAMP or TIMESTAMPTZ",
 						args[0], relname)));
-		newdt = (Datum) 0;		/* keep compiler quiet */
+		newdt = DummyDatum;		/* keep compiler quiet */
 	}
 	newdtnull = false;
 
diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c
index da702011193..483327694ba 100644
--- a/contrib/sslinfo/sslinfo.c
+++ b/contrib/sslinfo/sslinfo.c
@@ -211,7 +211,7 @@ X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
 	pfree(string_fieldname);
 	index = X509_NAME_get_index_by_NID(name, nid, -1);
 	if (index < 0)
-		return (Datum) 0;
+		return DummyDatum;
 	data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, index));
 	return ASN1_STRING_to_text(data);
 }
@@ -245,7 +245,7 @@ ssl_client_dn_field(PG_FUNCTION_ARGS)
 
 	result = X509_NAME_field_to_text(X509_get_subject_name(MyProcPort->peer), fieldname);
 
-	if (!result)
+	if (!result.value) // XXX
 		PG_RETURN_NULL();
 	else
 		return result;
@@ -280,7 +280,7 @@ ssl_issuer_field(PG_FUNCTION_ARGS)
 
 	result = X509_NAME_field_to_text(X509_get_issuer_name(MyProcPort->peer), fieldname);
 
-	if (!result)
+	if (!result.value) // XXX
 		PG_RETURN_NULL();
 	else
 		return result;
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 74afdc0977f..950a3bcd573 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -593,7 +593,7 @@ crosstab(PG_FUNCTION_ARGS)
 	/* release SPI related resources (and return to caller's context) */
 	SPI_finish();
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
@@ -695,7 +695,7 @@ crosstab_hash(PG_FUNCTION_ARGS)
 	rsinfo->setDesc = tupdesc;
 	MemoryContextSwitchTo(oldcontext);
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
@@ -1047,7 +1047,7 @@ connectby_text(PG_FUNCTION_ARGS)
 	 * to build our tuples with, so the caller can verify we did what it was
 	 * expecting.
 	 */
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 PG_FUNCTION_INFO_V1(connectby_text_serial);
@@ -1126,7 +1126,7 @@ connectby_text_serial(PG_FUNCTION_ARGS)
 	 * to build our tuples with, so the caller can verify we did what it was
 	 * expecting.
 	 */
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 4ac291c8251..9f5a813b77a 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -883,5 +883,5 @@ xpath_table(PG_FUNCTION_ARGS)
 	 * to build our tuples with, so the caller can verify we did what it was
 	 * expecting.
 	 */
-	return (Datum) 0;
+	PG_RETURN_DUMMY();  // XXX?
 }
diff --git a/src/backend/access/brin/brin_bloom.c b/src/backend/access/brin/brin_bloom.c
index 7c3f7d454fc..041b262cf3e 100644
--- a/src/backend/access/brin/brin_bloom.c
+++ b/src/backend/access/brin/brin_bloom.c
@@ -693,14 +693,14 @@ brin_bloom_union(PG_FUNCTION_ARGS)
 	filter_a->nbits_set = pg_popcount((const char *) filter_a->data, nbytes);
 
 	/* if we decompressed filter_a, update the summary */
-	if (PointerGetDatum(filter_a) != col_a->bv_values[0])
+	if (PointerGetDatum(filter_a).value != col_a->bv_values[0].value)
 	{
 		pfree(DatumGetPointer(col_a->bv_values[0]));
 		col_a->bv_values[0] = PointerGetDatum(filter_a);
 	}
 
 	/* also free filter_b, if it was decompressed */
-	if (PointerGetDatum(filter_b) != col_b->bv_values[0])
+	if (PointerGetDatum(filter_b).value != col_b->bv_values[0].value)
 		pfree(filter_b);
 
 	PG_RETURN_VOID();
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index b86ca5744a3..882b1c4cdda 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -229,7 +229,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 	{
 		pfree(DatumGetPointer(column->bv_values[INCLUSION_UNION]));
 
-		if (result == newval)
+		if (result.value == newval.value)
 			result = datumCopy(result, attr->attbyval, attr->attlen);
 	}
 	column->bv_values[INCLUSION_UNION] = result;
@@ -525,7 +525,7 @@ brin_inclusion_union(PG_FUNCTION_ARGS)
 	{
 		pfree(DatumGetPointer(col_a->bv_values[INCLUSION_UNION]));
 
-		if (result == col_b->bv_values[INCLUSION_UNION])
+		if (result.value == col_b->bv_values[INCLUSION_UNION].value)
 			result = datumCopy(result, attr->attbyval, attr->attlen);
 	}
 	col_a->bv_values[INCLUSION_UNION] = result;
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 79c5a0aa185..52132aa4113 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -193,7 +193,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			matches = 0;
+			matches = DummyDatum;
 			break;
 	}
 
diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index e323c0447d0..4e305e469f3 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -799,7 +799,7 @@ brin_range_deserialize(int maxvalues, SerializedRanges *serialized)
 	{
 		if (typbyval)			/* simple by-value data types */
 		{
-			Datum		v = 0;
+			Datum		v;
 
 			memcpy(&v, ptr, typlen);
 
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 1173a6d81b5..15c828b67b9 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -759,7 +759,7 @@ heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
 			break;
 		default:
 			elog(ERROR, "invalid attnum: %d", attnum);
-			result = 0;			/* keep compiler quiet */
+			result = DummyDatum;			/* keep compiler quiet */
 			break;
 	}
 	return result;
@@ -1041,7 +1041,7 @@ expand_tuple(HeapTuple *targetHeapTuple,
 					 &bitMask,
 					 &targetData,
 					 infoMask,
-					 (Datum) 0,
+					 DummyDatum,
 					 true);
 		}
 	}							/* end loop over missing attributes */
@@ -1375,7 +1375,7 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
 
 		if (hasnulls && att_isnull(attnum, bp))
 		{
-			values[attnum] = (Datum) 0;
+			values[attnum] = DummyDatum;
 			isnull[attnum] = true;
 			slow = true;		/* can't use attcacheoff anymore */
 			continue;
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c
index 1986b943a28..11fa2332d09 100644
--- a/src/backend/access/common/indextuple.c
+++ b/src/backend/access/common/indextuple.c
@@ -494,7 +494,7 @@ index_deform_tuple_internal(TupleDesc tupleDescriptor,
 
 		if (hasnulls && att_isnull(attnum, bp))
 		{
-			values[attnum] = (Datum) 0;
+			//values[attnum] = DummyDatum;
 			isnull[attnum] = true;
 			slow = true;		/* can't use attcacheoff anymore */
 			continue;
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 594a657ea1a..f7811bd2593 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1337,7 +1337,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
 	if (astate)
 		result = makeArrayResult(astate, CurrentMemoryContext);
 	else
-		result = (Datum) 0;
+		result = DummyDatum;
 
 	return result;
 }
@@ -1575,7 +1575,7 @@ parseLocalRelOptions(local_relopts *relopts, Datum options, bool validate)
 		i++;
 	}
 
-	if (options != (Datum) 0)
+	if (options.value != DummyDatum.value)
 		parseRelOptionsInternal(options, validate, values, nopts);
 
 	return values;
@@ -2019,7 +2019,7 @@ build_local_reloptions(local_relopts *relopts, Datum options, bool validate)
 bytea *
 partitioned_table_reloptions(Datum reloptions, bool validate)
 {
-	if (validate && reloptions)
+	if (validate && reloptions.value)
 		ereport(ERROR,
 				errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				errmsg("cannot specify storage parameters for a partitioned table"),
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 54dc2f4ab80..7234a5a902a 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -85,7 +85,7 @@ convert_tuples_by_position(TupleDesc indesc,
 	n = indesc->natts + 1;		/* +1 for NULL */
 	map->invalues = (Datum *) palloc(n * sizeof(Datum));
 	map->inisnull = (bool *) palloc(n * sizeof(bool));
-	map->invalues[0] = (Datum) 0;	/* set up the NULL entry */
+	map->invalues[0] = DummyDatum;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
 	return map;
@@ -141,7 +141,7 @@ convert_tuples_by_name_attrmap(TupleDesc indesc,
 	n = indesc->natts + 1;		/* +1 for NULL */
 	map->invalues = (Datum *) palloc(n * sizeof(Datum));
 	map->inisnull = (bool *) palloc(n * sizeof(bool));
-	map->invalues[0] = (Datum) 0;	/* set up the NULL entry */
+	map->invalues[0] = DummyDatum;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
 	return map;
@@ -226,7 +226,7 @@ execute_attr_map_slot(AttrMap *attrMap,
 		/* attrMap->attnums[i] == 0 means it's a NULL datum. */
 		if (j == -1)
 		{
-			outvalues[i] = (Datum) 0;
+			//outvalues[i] = DummyDatum;
 			outisnull[i] = true;
 		}
 		else
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 47b1898a064..df6989231ab 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -1436,7 +1436,7 @@ GinBufferStoreTuple(GinBuffer *buffer, GinTuple *tup)
 		if (tup->category == GIN_CAT_NORM_KEY)
 			buffer->key = datumCopy(key, buffer->typbyval, buffer->typlen);
 		else
-			buffer->key = (Datum) 0;
+			buffer->key = DummyDatum;
 	}
 
 	/*
@@ -1534,7 +1534,7 @@ GinBufferReset(GinBuffer *buffer)
 	 * Not required, but makes it more likely to trigger NULL dereference if
 	 * using the value incorrectly, etc.
 	 */
-	buffer->key = (Datum) 0;
+	buffer->key = DummyDatum;
 
 	buffer->attnum = 0;
 	buffer->category = 0;
@@ -2351,7 +2351,7 @@ _gin_parse_tuple_key(GinTuple *a)
 	Datum		key;
 
 	if (a->category != GIN_CAT_NORM_KEY)
-		return (Datum) 0;
+		return DummyDatum;
 
 	if (a->typbyval)
 	{
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index c2d1771bd77..d32cf8fe2ee 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -148,7 +148,7 @@ ginScanKeyAddHiddenEntry(GinScanOpaque so, GinScanKey key,
 	/* strategy is of no interest because this is not a partial-match item */
 	key->scanEntry[i] = ginFillScanEntry(so, key->attnum,
 										 InvalidStrategy, key->searchMode,
-										 (Datum) 0, queryCategory,
+										 DummyDatum, queryCategory,
 										 false, NULL);
 }
 
@@ -417,7 +417,7 @@ ginNewScanKey(IndexScanDesc scan)
 		hasNullQuery = true;
 		ginFillScanKey(so, FirstOffsetNumber,
 					   InvalidStrategy, GIN_SEARCH_MODE_EVERYTHING,
-					   (Datum) 0, 0,
+					   DummyDatum, 0,
 					   NULL, NULL, NULL, NULL);
 	}
 
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 78f7b7a2495..c0102eae915 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -501,7 +501,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	{
 		*nentries = 1;
 		entries = (Datum *) palloc(sizeof(Datum));
-		entries[0] = (Datum) 0;
+		entries[0] = DummyDatum;
 		*categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
 		(*categories)[0] = GIN_CAT_NULL_ITEM;
 		return entries;
@@ -523,7 +523,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	{
 		*nentries = 1;
 		entries = (Datum *) palloc(sizeof(Datum));
-		entries[0] = (Datum) 0;
+		entries[0] = DummyDatum;
 		*categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
 		(*categories)[0] = GIN_CAT_EMPTY_ITEM;
 		return entries;
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index 392163cb229..ba3479c8661 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -1396,7 +1396,8 @@ gist_point_consistent(PG_FUNCTION_ARGS)
 														  PointerGetDatum(entry),
 														  PolygonPGetDatum(query),
 														  Int16GetDatum(RTOverlapStrategyNumber),
-														  0, PointerGetDatum(recheck)));
+														  DummyDatum,
+														  PointerGetDatum(recheck)));
 
 				if (GIST_LEAF(entry) && result)
 				{
@@ -1423,7 +1424,8 @@ gist_point_consistent(PG_FUNCTION_ARGS)
 														  PointerGetDatum(entry),
 														  CirclePGetDatum(query),
 														  Int16GetDatum(RTOverlapStrategyNumber),
-														  0, PointerGetDatum(recheck)));
+														  DummyDatum,
+														  PointerGetDatum(recheck)));
 
 				if (GIST_LEAF(entry) && result)
 				{
@@ -1719,9 +1721,9 @@ gist_bbox_zorder_abbrev_convert(Datum original, SortSupport ssup)
 	z = point_zorder_internal(p->x, p->y);
 
 #if SIZEOF_DATUM == 8
-	return (Datum) z;
+	return UInt64GetDatum(z);
 #else
-	return (Datum) (z >> 32);
+	return (Datum) (z >> 32); // FIXME
 #endif
 }
 
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index c0aa7d0222f..5f13682e6f6 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -188,7 +188,7 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
 		/* If this column was all NULLs, the union is NULL */
 		if (evec->n == 0)
 		{
-			attr[i] = (Datum) 0;
+			attr[i] = DummyDatum;
 			isnull[i] = true;
 		}
 		else
@@ -249,7 +249,7 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno,
 	if (isnull1 && isnull2)
 	{
 		*dstisnull = true;
-		*dst = (Datum) 0;
+		*dst = DummyDatum;
 	}
 	else
 	{
@@ -568,7 +568,7 @@ gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
 						  dep->leafkey);
 	}
 	else
-		gistentryinit(*e, (Datum) 0, r, pg, o, l);
+		gistentryinit(*e, DummyDatum, r, pg, o, l);
 }
 
 IndexTuple
@@ -604,7 +604,7 @@ gistCompressValues(GISTSTATE *giststate, Relation r,
 	for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
 	{
 		if (isnull[i])
-			compatt[i] = (Datum) 0;
+			compatt[i] = DummyDatum;
 		else
 		{
 			GISTENTRY	centry;
@@ -632,7 +632,7 @@ gistCompressValues(GISTSTATE *giststate, Relation r,
 		for (; i < r->rd_att->natts; i++)
 		{
 			if (isnull[i])
-				compatt[i] = (Datum) 0;
+				compatt[i] = DummyDatum;
 			else
 				compatt[i] = attdata[i];
 		}
@@ -682,7 +682,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
 			if (!isnull[i])
 				fetchatt[i] = gistFetchAtt(giststate, i, datum, r);
 			else
-				fetchatt[i] = (Datum) 0;
+				fetchatt[i] = DummyDatum;
 		}
 		else if (giststate->compressFn[i].fn_oid == InvalidOid)
 		{
@@ -693,7 +693,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
 			if (!isnull[i])
 				fetchatt[i] = datum;
 			else
-				fetchatt[i] = (Datum) 0;
+				fetchatt[i] = DummyDatum;
 		}
 		else
 		{
@@ -703,7 +703,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
 			 * in this column, and we can replace it with a NULL.
 			 */
 			isnull[i] = true;
-			fetchatt[i] = (Datum) 0;
+			fetchatt[i] = DummyDatum;
 		}
 	}
 
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 219df1971da..c6ade655c03 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -998,7 +998,7 @@ index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes,
 			}
 			else
 			{
-				scan->xs_orderbyvals[i] = (Datum) 0;
+				scan->xs_orderbyvals[i] = DummyDatum;
 				scan->xs_orderbynulls[i] = true;
 			}
 		}
@@ -1012,7 +1012,7 @@ index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes,
 			}
 			else
 			{
-				scan->xs_orderbyvals[i] = (Datum) 0;
+				scan->xs_orderbyvals[i] = DummyDatum;
 				scan->xs_orderbynulls[i] = true;
 			}
 		}
diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c
index e1b52acd20d..8723093e752 100644
--- a/src/backend/access/nbtree/nbtcompare.c
+++ b/src/backend/access/nbtree/nbtcompare.c
@@ -88,7 +88,7 @@ bool_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -104,7 +104,7 @@ bool_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
@@ -160,7 +160,7 @@ int2_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -176,7 +176,7 @@ int2_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
@@ -228,7 +228,7 @@ int4_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -244,7 +244,7 @@ int4_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
@@ -316,7 +316,7 @@ int8_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -332,7 +332,7 @@ int8_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
@@ -482,7 +482,7 @@ oid_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -498,7 +498,7 @@ oid_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
@@ -561,7 +561,7 @@ char_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -577,7 +577,7 @@ char_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
diff --git a/src/backend/access/nbtree/nbtpreprocesskeys.c b/src/backend/access/nbtree/nbtpreprocesskeys.c
index 21c519cd108..cceadede0f9 100644
--- a/src/backend/access/nbtree/nbtpreprocesskeys.c
+++ b/src/backend/access/nbtree/nbtpreprocesskeys.c
@@ -1942,7 +1942,7 @@ _bt_preprocess_array_keys(IndexScanDesc scan, int *new_numberOfKeys)
 								   InvalidOid,	/* opclass input subtype */
 								   collation,	/* index column's collation */
 								   cmp_proc,	/* equality operator's proc */
-								   (Datum) 0);	/* constant */
+								   DummyDatum);	/* constant */
 
 			/* Initialize generic BTArrayKeyInfo fields */
 			so->arrayKeys[numArrayKeys].scan_key = numArrayKeyData;
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index fdff960c130..e68e361c07a 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -608,7 +608,7 @@ btestimateparallelscan(Relation rel, int nkeys, int norderbys)
 	 * Pessimistically assume that all attributes prior to the least
 	 * significant attribute require a skip array (and an associated key)
 	 */
-	genericattrspace = datumEstimateSpace((Datum) 0, false, true,
+	genericattrspace = datumEstimateSpace(DummyDatum, false, true,
 										  sizeof(Datum));
 	for (int attnum = 1; attnum < nkeyatts; attnum++)
 	{
@@ -627,7 +627,7 @@ btestimateparallelscan(Relation rel, int nkeys, int norderbys)
 		if (attr->attbyval)
 		{
 			/* This index attribute stores pass-by-value datums */
-			Size		estfixed = datumEstimateSpace((Datum) 0, false,
+			Size		estfixed = datumEstimateSpace(DummyDatum, false,
 													  true, attr->attlen);
 
 			estnbtreeshared = add_size(estnbtreeshared, estfixed);
@@ -688,7 +688,7 @@ _bt_parallel_serialize_arrays(Relation rel, BTParallelScanDesc btscan,
 		if (skey->sk_flags & (SK_BT_MINVAL | SK_BT_MAXVAL))
 		{
 			/* No sk_argument datum to serialize */
-			Assert(skey->sk_argument == 0);
+			Assert(skey->sk_argument.value == 0);
 			continue;
 		}
 
@@ -726,9 +726,9 @@ _bt_parallel_restore_arrays(Relation rel, BTParallelScanDesc btscan,
 		}
 
 		/* Restore skip array by restoring its key directly */
-		if (!array->attbyval && skey->sk_argument)
+		if (!array->attbyval && DatumGetPointer(skey->sk_argument))
 			pfree(DatumGetPointer(skey->sk_argument));
-		skey->sk_argument = (Datum) 0;
+		skey->sk_argument = DummyDatum;
 		memcpy(&skey->sk_flags, datumshared, sizeof(int));
 		datumshared += sizeof(int);
 
@@ -743,7 +743,7 @@ _bt_parallel_restore_arrays(Relation rel, BTParallelScanDesc btscan,
 		skey->sk_argument = datumRestore(&datumshared, &isnull);
 		if (isnull)
 		{
-			Assert(skey->sk_argument == 0);
+			Assert(skey->sk_argument.value == 0);
 			Assert(skey->sk_flags & SK_SEARCHNULL);
 			Assert(skey->sk_flags & SK_ISNULL);
 		}
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index d69798795b4..45f7ae720e2 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -1133,7 +1133,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 										   InvalidOid,
 										   InvalidOid,
 										   InvalidOid,
-										   (Datum) 0);
+										   DummyDatum);
 				}
 
 				/*
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 9aed207995f..6c0ca1cdccf 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -132,7 +132,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 	for (i = 0; i < indnkeyatts; i++)
 	{
 		FmgrInfo   *procinfo;
-		Datum		arg;
+		Datum		arg = DummyDatum;
 		bool		null;
 		int			flags;
 
@@ -151,7 +151,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 			arg = index_getattr(itup, i + 1, itupdesc, &null);
 		else
 		{
-			arg = (Datum) 0;
+			//arg = DummyDatum;
 			null = true;
 		}
 		flags = (null ? SK_ISNULL : 0) | (indoption[i] << SK_BT_INDOPTION_SHIFT);
@@ -568,7 +568,7 @@ _bt_skiparray_set_element(Relation rel, ScanKey skey, BTArrayKeyInfo *array,
 	}
 
 	/* Free memory previously allocated for sk_argument if needed */
-	if (!array->attbyval && skey->sk_argument)
+	if (!array->attbyval && DatumGetPointer(skey->sk_argument))
 		pfree(DatumGetPointer(skey->sk_argument));
 
 	/* tupdatum becomes new sk_argument/new current element */
@@ -589,11 +589,11 @@ _bt_skiparray_set_isnull(Relation rel, ScanKey skey, BTArrayKeyInfo *array)
 	Assert(array->null_elem && !array->low_compare && !array->high_compare);
 
 	/* Free memory previously allocated for sk_argument if needed */
-	if (!array->attbyval && skey->sk_argument)
+	if (!array->attbyval && DatumGetPointer(skey->sk_argument))
 		pfree(DatumGetPointer(skey->sk_argument));
 
 	/* NULL becomes new sk_argument/new current element */
-	skey->sk_argument = (Datum) 0;
+	skey->sk_argument = DummyDatum;
 	skey->sk_flags &= ~(SK_BT_MINVAL | SK_BT_MAXVAL |
 						SK_BT_NEXT | SK_BT_PRIOR);
 	skey->sk_flags |= (SK_SEARCHNULL | SK_ISNULL);
@@ -664,11 +664,11 @@ _bt_array_set_low_or_high(Relation rel, ScanKey skey, BTArrayKeyInfo *array,
 	Assert(array->num_elems == -1);
 
 	/* Free memory previously allocated for sk_argument if needed */
-	if (!array->attbyval && skey->sk_argument)
+	if (!array->attbyval && DatumGetPointer(skey->sk_argument))
 		pfree(DatumGetPointer(skey->sk_argument));
 
 	/* Reset flags */
-	skey->sk_argument = (Datum) 0;
+	skey->sk_argument = DummyDatum;
 	skey->sk_flags &= ~(SK_SEARCHNULL | SK_ISNULL |
 						SK_BT_MINVAL | SK_BT_MAXVAL |
 						SK_BT_NEXT | SK_BT_PRIOR);
@@ -816,7 +816,7 @@ _bt_array_decrement(Relation rel, ScanKey skey, BTArrayKeyInfo *array)
 	}
 
 	/* Accept value returned by opclass decrement callback */
-	if (!array->attbyval && skey->sk_argument)
+	if (!array->attbyval && DatumGetPointer(skey->sk_argument))
 		pfree(DatumGetPointer(skey->sk_argument));
 	skey->sk_argument = dec_sk_argument;
 
@@ -949,7 +949,7 @@ _bt_array_increment(Relation rel, ScanKey skey, BTArrayKeyInfo *array)
 	}
 
 	/* Accept value returned by opclass increment callback */
-	if (!array->attbyval && skey->sk_argument)
+	if (!array->attbyval && DatumGetPointer(skey->sk_argument))
 		pfree(DatumGetPointer(skey->sk_argument));
 	skey->sk_argument = inc_sk_argument;
 
@@ -2094,7 +2094,7 @@ _bt_verify_keys_with_arraykeys(IndexScanDesc scan)
 			return false;
 
 		if (array->num_elems != -1 &&
-			cur->sk_argument != array->elem_values[array->cur_elem])
+			cur->sk_argument.value != array->elem_values[array->cur_elem].value)
 			return false;
 		if (cur->sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD))
 		{
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index af6b27b2135..837f3e0018c 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -755,7 +755,7 @@ doPickSplit(Relation index, SpGistState *state,
 			if (it->tupstate == SPGIST_LIVE)
 			{
 				in.datums[nToInsert] =
-					isNulls ? (Datum) 0 : SGLTDATUM(it, state);
+					isNulls ? DummyDatum : SGLTDATUM(it, state);
 				oldLeafs[nToInsert] = it;
 				nToInsert++;
 				toDelete[nToDelete] = i;
@@ -781,7 +781,7 @@ doPickSplit(Relation index, SpGistState *state,
 			if (it->tupstate == SPGIST_LIVE)
 			{
 				in.datums[nToInsert] =
-					isNulls ? (Datum) 0 : SGLTDATUM(it, state);
+					isNulls ? DummyDatum : SGLTDATUM(it, state);
 				oldLeafs[nToInsert] = it;
 				nToInsert++;
 				toDelete[nToDelete] = i;
@@ -814,7 +814,7 @@ doPickSplit(Relation index, SpGistState *state,
 	 * for the picksplit function.  So don't increment nToInsert yet.
 	 */
 	in.datums[in.nTuples] =
-		isNulls ? (Datum) 0 : SGLTDATUM(newLeafTuple, state);
+		isNulls ? DummyDatum : SGLTDATUM(newLeafTuple, state);
 	oldLeafs[in.nTuples] = newLeafTuple;
 	in.nTuples++;
 
@@ -880,7 +880,7 @@ doPickSplit(Relation index, SpGistState *state,
 			/*
 			 * Nulls tree can contain only null key values.
 			 */
-			leafDatums[spgKeyColumn] = (Datum) 0;
+			leafDatums[spgKeyColumn] = DummyDatum;
 			leafIsnulls[spgKeyColumn] = true;
 
 			newLeafs[i] = spgFormLeafTuple(state, &oldLeafs[i]->heapPtr,
@@ -926,7 +926,7 @@ doPickSplit(Relation index, SpGistState *state,
 	 */
 	for (i = 0; i < out.nNodes; i++)
 	{
-		Datum		label = (Datum) 0;
+		Datum		label = DummyDatum;
 		bool		labelisnull = (out.nodeLabels == NULL);
 
 		if (!labelisnull)
@@ -1749,7 +1749,7 @@ spgSplitNodeAction(Relation index, SpGistState *state,
 
 	for (i = 0; i < out->result.splitTuple.prefixNNodes; i++)
 	{
-		Datum		label = (Datum) 0;
+		Datum		label = DummyDatum;
 		bool		labelisnull;
 
 		labelisnull = (out->result.splitTuple.prefixNodeLabels == NULL);
@@ -1967,7 +1967,7 @@ spgdoinsert(Relation index, SpGistState *state,
 		}
 	}
 	else
-		leafDatums[spgKeyColumn] = (Datum) 0;
+		leafDatums[spgKeyColumn] = DummyDatum;
 
 	/* Likewise, ensure that any INCLUDE values are not toasted */
 	for (int i = spgFirstIncludeColumn; i < leafDescriptor->natts; i++)
@@ -1980,7 +1980,7 @@ spgdoinsert(Relation index, SpGistState *state,
 				leafDatums[i] = datums[i];
 		}
 		else
-			leafDatums[i] = (Datum) 0;
+			leafDatums[i] = DummyDatum;
 	}
 
 	/*
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index 25893050c58..cc26ea1ab04 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -137,7 +137,7 @@ spgAddStartItem(SpGistScanOpaque so, bool isnull)
 				   FirstOffsetNumber);
 	startEntry->isLeaf = false;
 	startEntry->level = 0;
-	startEntry->value = (Datum) 0;
+	startEntry->value = DummyDatum;
 	startEntry->leafTuple = NULL;
 	startEntry->traversalValue = NULL;
 	startEntry->recheck = false;
@@ -477,7 +477,7 @@ spgNewHeapItem(SpGistScanOpaque so, int level, SpGistLeafTuple leafTuple,
 	 */
 	if (so->want_itup)
 	{
-		item->value = isnull ? (Datum) 0 :
+		item->value = isnull ? DummyDatum :
 			datumCopy(leafValue, so->state.attType.attbyval,
 					  so->state.attType.attlen);
 
@@ -495,7 +495,7 @@ spgNewHeapItem(SpGistScanOpaque so, int level, SpGistLeafTuple leafTuple,
 	}
 	else
 	{
-		item->value = (Datum) 0;
+		item->value = DummyDatum;
 		item->leafTuple = NULL;
 	}
 	item->traversalValue = NULL;
@@ -527,7 +527,7 @@ spgLeafTest(SpGistScanOpaque so, SpGistSearchItem *item,
 	{
 		/* Should not have arrived on a nulls page unless nulls are wanted */
 		Assert(so->searchNulls);
-		leafValue = (Datum) 0;
+		leafValue = DummyDatum;
 		distances = NULL;
 		recheck = false;
 		recheckDistances = false;
@@ -552,7 +552,7 @@ spgLeafTest(SpGistScanOpaque so, SpGistSearchItem *item,
 		in.returnData = so->want_itup;
 		in.leafDatum = SGLTDATUM(leafTuple, &so->state);
 
-		out.leafValue = (Datum) 0;
+		out.leafValue = DummyDatum;
 		out.recheck = false;
 		out.distances = NULL;
 		out.recheckDistances = false;
@@ -644,7 +644,7 @@ spgMakeInnerItem(SpGistScanOpaque so,
 		? datumCopy(out->reconstructedValues[i],
 					so->state.attLeafType.attbyval,
 					so->state.attLeafType.attlen)
-		: (Datum) 0;
+		: DummyDatum;
 
 	item->leafTuple = NULL;
 
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index 9b86c016acb..299cf90fdd5 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -1132,7 +1132,7 @@ spgDeformLeafTuple(SpGistLeafTuple tup, TupleDesc tupleDescriptor,
 		 */
 		Assert(!hasNullsMask);
 
-		datums[spgKeyColumn] = (Datum) 0;
+		datums[spgKeyColumn] = DummyDatum;
 		isnulls[spgKeyColumn] = true;
 		return;
 	}
diff --git a/src/backend/access/transam/rmgr.c b/src/backend/access/transam/rmgr.c
index 1b7499726eb..1c56dbc8504 100644
--- a/src/backend/access/transam/rmgr.c
+++ b/src/backend/access/transam/rmgr.c
@@ -166,5 +166,5 @@ pg_get_wal_resource_managers(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 7918176fc58..dcf13acb38a 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -379,7 +379,7 @@ MarkAsPreparing(FullTransactionId fxid, const char *gid,
 	/* on first call, register the exit hook */
 	if (!twophaseExitRegistered)
 	{
-		before_shmem_exit(AtProcExit_Twophase, 0);
+		before_shmem_exit(AtProcExit_Twophase, DummyDatum);
 		twophaseExitRegistered = true;
 	}
 
@@ -559,7 +559,7 @@ LockGXact(const char *gid, Oid user)
 	/* on first call, register the exit hook */
 	if (!twophaseExitRegistered)
 	{
-		before_shmem_exit(AtProcExit_Twophase, 0);
+		before_shmem_exit(AtProcExit_Twophase, DummyDatum);
 		twophaseExitRegistered = true;
 	}
 
diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c
index ed3aacabc98..acdcc6b93f0 100644
--- a/src/backend/access/transam/xlogprefetcher.c
+++ b/src/backend/access/transam/xlogprefetcher.c
@@ -845,7 +845,7 @@ pg_stat_get_recovery_prefetch(PG_FUNCTION_ARGS)
 	values[9] = Int32GetDatum(SharedStats->io_depth);
 	tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/backup/walsummaryfuncs.c b/src/backend/backup/walsummaryfuncs.c
index d6dd131da14..3ff4961010d 100644
--- a/src/backend/backup/walsummaryfuncs.c
+++ b/src/backend/backup/walsummaryfuncs.c
@@ -58,7 +58,7 @@ pg_available_wal_summaries(PG_FUNCTION_ARGS)
 		tuplestore_puttuple(rsi->setResult, tuple);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -167,7 +167,7 @@ pg_wal_summary_contents(PG_FUNCTION_ARGS)
 	DestroyBlockRefTableReader(reader);
 	FileClose(io.file);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 9833f52c1be..6b1b2779f14 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -239,7 +239,7 @@ Boot_CreateStmt:
 													  shared_relation,
 													  mapped_relation,
 													  ONCOMMIT_NOOP,
-													  (Datum) 0,
+													  DummyDatum,
 													  false,
 													  true,
 													  false,
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 9ca8a88dc91..a961b5a0616 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -3101,7 +3101,7 @@ object_aclmask_ext(Oid classid, Oid objectid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(get_object_type(classid, objectid), ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = DummyDatum;
 	}
 	else
 	{
@@ -3338,7 +3338,7 @@ pg_class_aclmask_ext(Oid table_oid, Oid roleid, AclMode mask,
 				acl = acldefault(OBJECT_TABLE, ownerId);
 				break;
 		}
-		aclDatum = (Datum) 0;
+		aclDatum = DummyDatum;
 	}
 	else
 	{
@@ -3430,7 +3430,7 @@ pg_parameter_aclmask(const char *name, Oid roleid, AclMode mask, AclMaskHow how)
 		{
 			/* No ACL, so build default ACL */
 			acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
-			aclDatum = (Datum) 0;
+			aclDatum = DummyDatum;
 		}
 		else
 		{
@@ -3485,7 +3485,7 @@ pg_parameter_acl_aclmask(Oid acl_oid, Oid roleid, AclMode mask, AclMaskHow how)
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_PARAMETER_ACL, BOOTSTRAP_SUPERUSERID);
-		aclDatum = (Datum) 0;
+		aclDatum = DummyDatum;
 	}
 	else
 	{
@@ -3565,7 +3565,7 @@ pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = DummyDatum;
 	}
 	else
 	{
@@ -3659,7 +3659,7 @@ pg_namespace_aclmask_ext(Oid nsp_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_SCHEMA, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = DummyDatum;
 	}
 	else
 	{
@@ -3795,7 +3795,7 @@ pg_type_aclmask_ext(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_TYPE, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = DummyDatum;
 	}
 	else
 	{
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index fd6537567ea..65c1264605d 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -902,7 +902,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
  * Tuple data is taken from new_rel_desc->rd_rel, except for the
  * variable-width fields which are not present in a cached reldesc.
  * relacl and reloptions are passed in Datum form (to avoid having
- * to reference the data types in heap.h).  Pass (Datum) 0 to set them
+ * to reference the data types in heap.h).  Pass DummyDatum to set them
  * to NULL.
  * --------------------------------
  */
@@ -953,11 +953,11 @@ InsertPgClassTuple(Relation pg_class_desc,
 	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);
-	if (relacl != (Datum) 0)
+	if (relacl.value != DummyDatum.value)
 		values[Anum_pg_class_relacl - 1] = relacl;
 	else
 		nulls[Anum_pg_class_relacl - 1] = true;
-	if (reloptions != (Datum) 0)
+	if (reloptions.value != DummyDatum.value)
 		values[Anum_pg_class_reloptions - 1] = reloptions;
 	else
 		nulls[Anum_pg_class_reloptions - 1] = true;
@@ -1104,7 +1104,7 @@ AddNewRelationType(const char *typeName,
  *	shared_relation: true if it's to be a shared relation
  *	mapped_relation: true if the relation will use the relfilenumber map
  *	oncommit: ON COMMIT marking (only relevant if it's a temp table)
- *	reloptions: reloptions in Datum form, or (Datum) 0 if none
+ *	reloptions: reloptions in Datum form, or DummyDatum if none
  *	use_user_acl: true if should look for user-defined default permissions;
  *		if false, relacl is always set NULL
  *	allow_system_table_mods: true to allow creation in system namespaces
@@ -3929,12 +3929,12 @@ StorePartitionKey(Relation rel,
 		pfree(exprString);
 	}
 	else
-		partexprDatum = (Datum) 0;
+		partexprDatum = DummyDatum;
 
 	pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
 
 	/* Only this can ever be NULL */
-	if (!partexprDatum)
+	if (!partexprDatum.value)
 		nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
 
 	values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index c4029a4f3d3..895825c67cf 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -522,7 +522,7 @@ AppendAttributeTuples(Relation indexRelation, const Datum *attopts, const Nullab
 
 		for (int i = 0; i < indexRelation->rd_att->natts; i++)
 		{
-			if (attopts[i])
+			if (attopts[i].value)
 				attrs_extra[i].attoptions.value = attopts[i];
 			else
 				attrs_extra[i].attoptions.isnull = true;
@@ -608,7 +608,7 @@ UpdateIndexRelation(Oid indexoid,
 		pfree(exprsString);
 	}
 	else
-		exprsDatum = (Datum) 0;
+		exprsDatum = DummyDatum;
 
 	/*
 	 * Convert the index predicate (if any) to a text datum.  Note we convert
@@ -623,7 +623,7 @@ UpdateIndexRelation(Oid indexoid,
 		pfree(predString);
 	}
 	else
-		predDatum = (Datum) 0;
+		predDatum = DummyDatum;
 
 
 	/*
@@ -654,10 +654,10 @@ UpdateIndexRelation(Oid indexoid,
 	values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);
 	values[Anum_pg_index_indoption - 1] = PointerGetDatum(indoption);
 	values[Anum_pg_index_indexprs - 1] = exprsDatum;
-	if (exprsDatum == (Datum) 0)
+	if (exprsDatum.value == DummyDatum.value)
 		nulls[Anum_pg_index_indexprs - 1] = true;
 	values[Anum_pg_index_indpred - 1] = predDatum;
-	if (predDatum == (Datum) 0)
+	if (predDatum.value == DummyDatum.value)
 		nulls[Anum_pg_index_indpred - 1] = true;
 
 	tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls);
@@ -1015,7 +1015,7 @@ index_create(Relation heapRelation,
 	 */
 	InsertPgClassTuple(pg_class, indexRelation,
 					   RelationGetRelid(indexRelation),
-					   (Datum) 0,
+					   DummyDatum,
 					   reloptions);
 
 	/* done with pg_class */
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index d97d632a7ef..9d576cb0b90 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -4522,7 +4522,7 @@ AtEOXact_Namespace(bool isCommit, bool parallel)
 	if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
 	{
 		if (isCommit)
-			before_shmem_exit(RemoveTempRelationsCallback, 0);
+			before_shmem_exit(RemoveTempRelationsCallback, DummyDatum);
 		else
 		{
 			myTempNamespace = InvalidOid;
@@ -4765,22 +4765,22 @@ InitializeSearchPath(void)
 		/* namespace name or ACLs may have changed */
 		CacheRegisterSyscacheCallback(NAMESPACEOID,
 									  InvalidationCallback,
-									  (Datum) 0);
+									  DummyDatum);
 
 		/* role name may affect the meaning of "$user" */
 		CacheRegisterSyscacheCallback(AUTHOID,
 									  InvalidationCallback,
-									  (Datum) 0);
+									  DummyDatum);
 
 		/* role membership may affect ACLs */
 		CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
 									  InvalidationCallback,
-									  (Datum) 0);
+									  DummyDatum);
 
 		/* database owner may affect ACLs */
 		CacheRegisterSyscacheCallback(DATABASEOID,
 									  InvalidationCallback,
-									  (Datum) 0);
+									  DummyDatum);
 
 		/* Force search path to be recomputed on next use */
 		baseSearchPathValid = false;
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index a05f8a87c1f..aee94a9aae3 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -654,7 +654,7 @@ AggregateCreate(const char *aggName,
 	for (i = 0; i < Natts_pg_aggregate; i++)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;
+		values[i] = DummyDatum;
 		replaces[i] = true;
 	}
 	values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 2d5ac1ea813..fb907fa36f5 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -179,7 +179,7 @@ CreateConstraintEntry(const char *constraintName,
 	for (i = 0; i < Natts_pg_constraint; i++)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;
+		values[i] = DummyDatum;
 	}
 
 	conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
index 04cc375caea..67191d24929 100644
--- a/src/backend/catalog/pg_conversion.c
+++ b/src/backend/catalog/pg_conversion.c
@@ -87,7 +87,7 @@ ConversionCreate(const char *conname, Oid connamespace,
 	for (i = 0; i < Natts_pg_conversion; i++)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;
+		values[i] = DummyDatum;
 	}
 
 	/* form a tuple */
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index 6f5634a4de6..a8bd27ab197 100644
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -76,7 +76,7 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
 	for (i = 0; i < Natts_pg_namespace; i++)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;
+		values[i] = DummyDatum;
 	}
 
 	nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId,
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index bfcfa643464..bee3e02b155 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -225,7 +225,7 @@ OperatorShellMake(const char *operatorName,
 	for (i = 0; i < Natts_pg_operator; ++i)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;	/* redundant, but safe */
+		values[i] = DummyDatum;	/* redundant, but safe */
 	}
 
 	/*
@@ -453,7 +453,7 @@ OperatorCreate(const char *operatorName,
 
 	for (i = 0; i < Natts_pg_operator; ++i)
 	{
-		values[i] = (Datum) NULL;
+		values[i] = DummyDatum;
 		replaces[i] = true;
 		nulls[i] = false;
 	}
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 75b17fed15e..d4a130aa704 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -162,7 +162,7 @@ ProcedureCreate(const char *procedureName,
 	/* note: the above is correct, we do NOT count output arguments */
 
 	/* Deconstruct array inputs */
-	if (allParameterTypes != PointerGetDatum(NULL))
+	if (allParameterTypes.value != PointerGetDatum(NULL).value)
 	{
 		/*
 		 * We expect the array to be a 1-D OID array; verify that. We don't
@@ -187,7 +187,7 @@ ProcedureCreate(const char *procedureName,
 		allParams = parameterTypes->values;
 	}
 
-	if (parameterModes != PointerGetDatum(NULL))
+	if (parameterModes.value != PointerGetDatum(NULL).value)
 	{
 		/*
 		 * We expect the array to be a 1-D CHAR array; verify that. We don't
@@ -233,7 +233,7 @@ ProcedureCreate(const char *procedureName,
 	/*
 	 * Apply the same tests to any OUT arguments.
 	 */
-	if (allParameterTypes != PointerGetDatum(NULL))
+	if (allParameterTypes.value != PointerGetDatum(NULL).value)
 	{
 		for (i = 0; i < allParamCount; i++)
 		{
@@ -320,7 +320,7 @@ ProcedureCreate(const char *procedureName,
 	for (i = 0; i < Natts_pg_proc; ++i)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) 0;
+		values[i] = DummyDatum;
 		replaces[i] = true;
 	}
 
@@ -344,15 +344,15 @@ ProcedureCreate(const char *procedureName,
 	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);
-	if (allParameterTypes != PointerGetDatum(NULL))
+	if (allParameterTypes.value != PointerGetDatum(NULL).value)
 		values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
 	else
 		nulls[Anum_pg_proc_proallargtypes - 1] = true;
-	if (parameterModes != PointerGetDatum(NULL))
+	if (parameterModes.value != PointerGetDatum(NULL).value)
 		values[Anum_pg_proc_proargmodes - 1] = parameterModes;
 	else
 		nulls[Anum_pg_proc_proargmodes - 1] = true;
-	if (parameterNames != PointerGetDatum(NULL))
+	if (parameterNames.value != PointerGetDatum(NULL).value)
 		values[Anum_pg_proc_proargnames - 1] = parameterNames;
 	else
 		nulls[Anum_pg_proc_proargnames - 1] = true;
@@ -360,7 +360,7 @@ ProcedureCreate(const char *procedureName,
 		values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults));
 	else
 		nulls[Anum_pg_proc_proargdefaults - 1] = true;
-	if (trftypes != PointerGetDatum(NULL))
+	if (trftypes.value != PointerGetDatum(NULL).value)
 		values[Anum_pg_proc_protrftypes - 1] = trftypes;
 	else
 		nulls[Anum_pg_proc_protrftypes - 1] = true;
@@ -373,7 +373,7 @@ ProcedureCreate(const char *procedureName,
 		values[Anum_pg_proc_prosqlbody - 1] = CStringGetTextDatum(nodeToString(prosqlbody));
 	else
 		nulls[Anum_pg_proc_prosqlbody - 1] = true;
-	if (proconfig != PointerGetDatum(NULL))
+	if (proconfig.value != PointerGetDatum(NULL).value)
 		values[Anum_pg_proc_proconfig - 1] = proconfig;
 	else
 		nulls[Anum_pg_proc_proconfig - 1] = true;
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index b36f81afb9d..384d26ead2a 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -80,7 +80,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
 	for (i = 0; i < Natts_pg_type; ++i)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;	/* redundant, but safe */
+		values[i] = DummyDatum;	/* redundant, but safe */
 	}
 
 	/*
@@ -343,7 +343,7 @@ TypeCreate(Oid newTypeOid,
 	{
 		nulls[i] = false;
 		replaces[i] = true;
-		values[i] = (Datum) 0;
+		values[i] = DummyDatum;
 	}
 
 	/*
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 874a8fc89ad..145cff6e3fe 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -47,7 +47,7 @@ static bool needs_toast_table(Relation rel);
  *		If the table needs a toast table, and doesn't already have one,
  *		then create a toast table for it.
  *
- * reloptions for the toast table can be passed, too.  Pass (Datum) 0
+ * reloptions for the toast table can be passed, too.  Pass DummyDatum
  * for default reloptions.
  *
  * We expect the caller to have verified that the relation is a table and have
@@ -107,7 +107,7 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
 			 relName);
 
 	/* create_toast_table does all the work */
-	if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0,
+	if (!create_toast_table(rel, toastOid, toastIndexOid, DummyDatum,
 							AccessExclusiveLock, false, InvalidOid))
 		elog(ERROR, "\"%s\" does not require a toast table",
 			 relName);
@@ -324,7 +324,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 				 list_make2("chunk_id", "chunk_seq"),
 				 BTREE_AM_OID,
 				 rel->rd_rel->reltablespace,
-				 collationIds, opclassIds, NULL, coloptions, NULL, (Datum) 0,
+				 collationIds, opclassIds, NULL, coloptions, NULL, DummyDatum,
 				 INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL);
 
 	table_close(toast_rel, NoLock);
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 7111d5d5334..8ad892afba1 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -967,7 +967,7 @@ compute_index_stats(Relation onerel, double totalrows,
 
 					if (isnull[attnum - 1])
 					{
-						exprvals[tcnt] = (Datum) 0;
+						exprvals[tcnt] = DummyDatum;
 						exprnulls[tcnt] = true;
 					}
 					else
@@ -1727,7 +1727,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 			else
 			{
 				nulls[i] = true;
-				values[i++] = (Datum) 0;
+				values[i++] = DummyDatum;
 			}
 		}
 		i = Anum_pg_statistic_stavalues1 - 1;
@@ -1748,7 +1748,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 			else
 			{
 				nulls[i] = true;
-				values[i++] = (Datum) 0;
+				values[i++] = DummyDatum;
 			}
 		}
 
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 4bd37d5beb5..84351c92ffc 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -1060,7 +1060,7 @@ Exec_ListenPreCommit(void)
 	 */
 	if (!unlistenExitRegistered)
 	{
-		before_shmem_exit(Async_UnlistenOnExit, 0);
+		before_shmem_exit(Async_UnlistenOnExit, DummyDatum);
 		unlistenExitRegistered = true;
 	}
 
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index b55221d44cd..b46b523dfe5 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -734,7 +734,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid NewAccessMethod,
 	reloptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
 								 &isNull);
 	if (isNull)
-		reloptions = (Datum) 0;
+		reloptions = DummyDatum;
 
 	if (relpersistence == RELPERSISTENCE_TEMP)
 		namespaceid = LookupCreationNamespace("pg_temp");
@@ -807,7 +807,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid NewAccessMethod,
 		reloptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
 									 &isNull);
 		if (isNull)
-			reloptions = (Datum) 0;
+			reloptions = DummyDatum;
 
 		NewHeapCreateToastTable(OIDNewHeap, reloptions, lockmode, toastid);
 
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index dfd2ab8e862..7f82c46a780 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -121,7 +121,7 @@ create_ctas_internal(List *attrList, IntoClause *into)
 	CommandCounterIncrement();
 
 	/* parse and validate reloptions for the toast table */
-	toast_options = transformRelOptions((Datum) 0,
+	toast_options = transformRelOptions(DummyDatum,
 										create->options,
 										"toast",
 										validnsps,
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 631fb0525f1..4cbadf1678d 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -1475,7 +1475,7 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS)
 							 values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index e6f9ab6dfd6..1fefa5c4ad0 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1257,7 +1257,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
 											t_sql,
 											CStringGetTextDatum("@extschema@"),
 											CStringGetTextDatum(qSchemaName));
-			if (t_sql != old && strpbrk(schemaName, quoting_relevant_chars))
+			if (t_sql.value != old.value && strpbrk(schemaName, quoting_relevant_chars))
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
@@ -1284,7 +1284,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
 											t_sql,
 											CStringGetTextDatum(repltoken),
 											CStringGetTextDatum(qSchemaName));
-			if (t_sql != old && strpbrk(schemaName, quoting_relevant_chars))
+			if (t_sql.value != old.value && strpbrk(schemaName, quoting_relevant_chars))
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
@@ -2093,12 +2093,12 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
 	values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
 	values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
 
-	if (extConfig == PointerGetDatum(NULL))
+	if (extConfig.value == PointerGetDatum(NULL).value)
 		nulls[Anum_pg_extension_extconfig - 1] = true;
 	else
 		values[Anum_pg_extension_extconfig - 1] = extConfig;
 
-	if (extCondition == PointerGetDatum(NULL))
+	if (extCondition.value == PointerGetDatum(NULL).value)
 		nulls[Anum_pg_extension_extcondition - 1] = true;
 	else
 		values[Anum_pg_extension_extcondition - 1] = extCondition;
@@ -2275,7 +2275,7 @@ pg_available_extensions(PG_FUNCTION_ARGS)
 		}
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -2344,7 +2344,7 @@ pg_available_extension_versions(PG_FUNCTION_ARGS)
 		}
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -2625,7 +2625,7 @@ pg_extension_update_paths(PG_FUNCTION_ARGS)
 		}
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -2861,7 +2861,7 @@ pg_get_loaded_modules(PG_FUNCTION_ARGS)
 							 values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 0335e982b31..d2e0c0545e9 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -493,7 +493,7 @@ interpret_function_parameter_list(ParseState *pstate,
 	{
 		for (i = 0; i < parameterCount; i++)
 		{
-			if (paramNames[i] == PointerGetDatum(NULL))
+			if (paramNames[i].value == PointerGetDatum(NULL).value)
 				paramNames[i] = CStringGetTextDatum("");
 		}
 		*parameterNames = construct_array_builtin(paramNames, parameterCount, TEXTOID);
@@ -1506,7 +1506,7 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
 
 		if (a == NULL)
 		{
-			repl_val[Anum_pg_proc_proconfig - 1] = (Datum) 0;
+			repl_val[Anum_pg_proc_proconfig - 1] = DummyDatum;
 			repl_null[Anum_pg_proc_proconfig - 1] = true;
 		}
 		else
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 6f753ab6d7a..9fc69e13944 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -370,17 +370,17 @@ CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts)
 	fmgr_info(F_ARRAY_EQ, &fm);
 	for (i = 0; i < natts; i++)
 	{
-		Datum		opt1 = opts1 ? opts1[i] : (Datum) 0;
-		Datum		opt2 = opts2 ? opts2[i] : (Datum) 0;
+		Datum		opt1 = opts1 ? opts1[i] : DummyDatum;
+		Datum		opt2 = opts2 ? opts2[i] : DummyDatum;
 
-		if (opt1 == (Datum) 0)
+		if (opt1.value == DummyDatum.value)
 		{
-			if (opt2 == (Datum) 0)
+			if (opt2.value == DummyDatum.value)
 				continue;
 			else
 				return false;
 		}
-		else if (opt2 == (Datum) 0)
+		else if (opt2.value == DummyDatum.value)
 			return false;
 
 		/*
@@ -908,7 +908,7 @@ DefineIndex(Oid tableId,
 	/*
 	 * Parse AM-specific options, convert to text array form, validate.
 	 */
-	reloptions = transformRelOptions((Datum) 0, stmt->options,
+	reloptions = transformRelOptions(DummyDatum, stmt->options,
 									 NULL, NULL, false, false);
 
 	(void) index_reloptions(amoptions, reloptions, true);
@@ -2046,7 +2046,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 						 errmsg("including column does not support NULLS FIRST/LAST options")));
 
 			opclassOids[attn] = InvalidOid;
-			opclassOptions[attn] = (Datum) 0;
+			opclassOptions[attn] = DummyDatum;
 			colOptions[attn] = 0;
 			collationOids[attn] = InvalidOid;
 			attn++;
@@ -2240,11 +2240,11 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 			Assert(attn < nkeycols);
 
 			opclassOptions[attn] =
-				transformRelOptions((Datum) 0, attribute->opclassopts,
+				transformRelOptions(DummyDatum, attribute->opclassopts,
 									NULL, NULL, false, false);
 		}
 		else
-			opclassOptions[attn] = (Datum) 0;
+			opclassOptions[attn] = DummyDatum;
 
 		attn++;
 	}
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 673648f1fc6..c2b9de95c1c 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -648,7 +648,7 @@ AlterOperator(AlterOperatorStmt *stmt)
 	/* Update the tuple */
 	for (i = 0; i < Natts_pg_operator; ++i)
 	{
-		values[i] = (Datum) 0;
+		values[i] = DummyDatum;
 		replaces[i] = false;
 		nulls[i] = false;
 	}
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 34b6410d6a2..c87cac06a7b 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -735,7 +735,7 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 		}
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
index e24d540cd45..f8a836e5e20 100644
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -497,7 +497,7 @@ CreateStatistics(CreateStatsStmt *stmt)
 		pfree(exprsString);
 	}
 	else
-		exprsDatum = (Datum) 0;
+		exprsDatum = DummyDatum;
 
 	statrel = table_open(StatisticExtRelationId, RowExclusiveLock);
 
@@ -519,7 +519,7 @@ CreateStatistics(CreateStatsStmt *stmt)
 	values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind);
 
 	values[Anum_pg_statistic_ext_stxexprs - 1] = exprsDatum;
-	if (exprsDatum == (Datum) 0)
+	if (exprsDatum.value == DummyDatum.value)
 		nulls[Anum_pg_statistic_ext_stxexprs - 1] = true;
 
 	/* insert it into pg_statistic_ext */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c6dd2e020da..da17d4c793c 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -929,7 +929,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 	/*
 	 * Parse and validate reloptions, if any.
 	 */
-	reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
+	reloptions = transformRelOptions(DummyDatum, stmt->options, NULL, validnsps,
 									 true, false);
 
 	switch (relkind)
@@ -5354,7 +5354,7 @@ ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
 			  tab->relkind == RELKIND_PARTITIONED_TABLE) &&
 			 tab->partition_constraint == NULL) ||
 			tab->relkind == RELKIND_MATVIEW)
-			AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
+			AlterTableCreateToastTable(tab->relid, DummyDatum, lockmode);
 	}
 }
 
@@ -9049,7 +9049,7 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
 	/* Generate new proposed attoptions (text array) */
 	datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
 							&isnull);
-	newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
+	newOptions = transformRelOptions(isnull ? DummyDatum : datum,
 									 castNode(List, options), NULL, NULL,
 									 false, isReset);
 	/* Validate new options */
@@ -9058,7 +9058,7 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
 	/* Build new tuple. */
 	memset(repl_null, false, sizeof(repl_null));
 	memset(repl_repl, false, sizeof(repl_repl));
-	if (newOptions != (Datum) 0)
+	if (newOptions.value != DummyDatum.value)
 		repl_val[Anum_pg_attribute_attoptions - 1] = newOptions;
 	else
 		repl_null[Anum_pg_attribute_attoptions - 1] = true;
@@ -16637,7 +16637,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 		 * If we're supposed to replace the reloptions list, we just pretend
 		 * there were none before.
 		 */
-		datum = (Datum) 0;
+		datum = DummyDatum;
 	}
 	else
 	{
@@ -16647,7 +16647,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 		datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
 								&isnull);
 		if (isnull)
-			datum = (Datum) 0;
+			datum = DummyDatum;
 	}
 
 	/* Generate new proposed reloptions (text array) */
@@ -16723,7 +16723,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 	memset(repl_null, false, sizeof(repl_null));
 	memset(repl_repl, false, sizeof(repl_repl));
 
-	if (newOptions != (Datum) 0)
+	if (newOptions.value != DummyDatum.value)
 		repl_val[Anum_pg_class_reloptions - 1] = newOptions;
 	else
 		repl_null[Anum_pg_class_reloptions - 1] = true;
@@ -16761,7 +16761,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 			 * If we're supposed to replace the reloptions list, we just
 			 * pretend there were none before.
 			 */
-			datum = (Datum) 0;
+			datum = DummyDatum;
 		}
 		else
 		{
@@ -16771,7 +16771,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 			datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
 									&isnull);
 			if (isnull)
-				datum = (Datum) 0;
+				datum = DummyDatum;
 		}
 
 		newOptions = transformRelOptions(datum, defList, "toast", validnsps,
@@ -16783,7 +16783,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 		memset(repl_null, false, sizeof(repl_null));
 		memset(repl_repl, false, sizeof(repl_repl));
 
-		if (newOptions != (Datum) 0)
+		if (newOptions.value != DummyDatum.value)
 			repl_val[Anum_pg_class_reloptions - 1] = newOptions;
 		else
 			repl_null[Anum_pg_class_reloptions - 1] = true;
@@ -21300,7 +21300,7 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
 	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_val[Anum_pg_class_relpartbound - 1] = DummyDatum;
 	new_null[Anum_pg_class_relpartbound - 1] = true;
 	new_repl[Anum_pg_class_relpartbound - 1] = true;
 	newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index df31eace47a..f6bce7d34ce 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -333,11 +333,11 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 	nulls[Anum_pg_tablespace_spcacl - 1] = true;
 
 	/* Generate new proposed spcoptions (text array) */
-	newOptions = transformRelOptions((Datum) 0,
+	newOptions = transformRelOptions(DummyDatum,
 									 stmt->options,
 									 NULL, NULL, false, false);
 	(void) tablespace_reloptions(newOptions, true);
-	if (newOptions != (Datum) 0)
+	if (newOptions.value != DummyDatum.value)
 		values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
 	else
 		nulls[Anum_pg_tablespace_spcoptions - 1] = true;
@@ -1052,7 +1052,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
 	/* Generate new proposed spcoptions (text array) */
 	datum = heap_getattr(tup, Anum_pg_tablespace_spcoptions,
 						 RelationGetDescr(rel), &isnull);
-	newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
+	newOptions = transformRelOptions(isnull ? DummyDatum : datum,
 									 stmt->options, NULL, NULL, false,
 									 stmt->isReset);
 	(void) tablespace_reloptions(newOptions, true);
@@ -1060,7 +1060,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
 	/* Build new tuple. */
 	memset(repl_null, false, sizeof(repl_null));
 	memset(repl_repl, false, sizeof(repl_repl));
-	if (newOptions != (Datum) 0)
+	if (newOptions.value != DummyDatum.value)
 		repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
 	else
 		repl_null[Anum_pg_tablespace_spcoptions - 1] = true;
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index c909d1b8bd8..ada433ab7ba 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -6676,7 +6676,7 @@ check_modified_virtual_generated(TupleDesc tupdesc, HeapTuple tuple)
 			if (!heap_attisnull(tuple, i + 1, tupdesc))
 			{
 				int			replCol = i + 1;
-				Datum		replValue = 0;
+				Datum		replValue = DummyDatum;
 				bool		replIsnull = true;
 
 				tuple = heap_modify_tuple_by_cols(tuple, tupdesc, 1, &replCol, &replValue, &replIsnull);
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index dc7df736fb8..eb979210d0c 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1244,7 +1244,7 @@ getTokenTypes(Oid prsId, List *tokennames)
 
 	/* lextype takes one dummy argument */
 	list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
-														 (Datum) 0));
+														 DummyDatum));
 
 	foreach(tn, tokennames)
 	{
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 1e3d4ab0e20..fe90d24a857 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -389,7 +389,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
 	}
 	else
 	{
-		validUntil_datum = (Datum) 0;
+		validUntil_datum = DummyDatum;
 		validUntil_null = true;
 	}
 
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index f1569879b52..74ae427461d 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -724,7 +724,7 @@ ExecBuildUpdateProjection(List *targetList,
 			scratch.opcode = EEOP_CONST;
 			scratch.resvalue = &state->resvalue;
 			scratch.resnull = &state->resnull;
-			scratch.d.constval.value = (Datum) 0;
+			scratch.d.constval.value = DummyDatum;
 			scratch.d.constval.isnull = true;
 			ExprEvalPushStep(state, &scratch);
 			/* ... then assign it to the result slot */
@@ -1477,7 +1477,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				if (subplan->subLinkType == MULTIEXPR_SUBLINK)
 				{
 					scratch.opcode = EEOP_CONST;
-					scratch.d.constval.value = (Datum) 0;
+					scratch.d.constval.value = DummyDatum;
 					scratch.d.constval.isnull = true;
 					ExprEvalPushStep(state, &scratch);
 					break;
@@ -4833,7 +4833,7 @@ ExecInitJsonExpr(JsonExpr *jsexpr, ExprState *state,
 	scratch->opcode = EEOP_CONST;
 	scratch->resvalue = resv;
 	scratch->resnull = resnull;
-	scratch->d.constval.value = (Datum) 0;
+	scratch->d.constval.value = DummyDatum;
 	scratch->d.constval.isnull = true;
 	ExprEvalPushStep(state, scratch);
 
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 0e1a74976f7..193b262110c 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -628,7 +628,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		EEO_CASE(EEOP_DONE_NO_RETURN)
 		{
 			Assert(isnull == NULL);
-			return (Datum) 0;
+			return DummyDatum;
 		}
 
 		EEO_CASE(EEOP_INNER_FETCHSOME)
@@ -1078,7 +1078,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			}
 			else if (*op->d.boolexpr.anynull)
 			{
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = DummyDatum;
 				*op->resnull = true;
 			}
 			else
@@ -1145,7 +1145,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			}
 			else if (*op->d.boolexpr.anynull)
 			{
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = DummyDatum;
 				*op->resnull = true;
 			}
 			else
@@ -1535,7 +1535,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 				/* if the arguments are equal return null */
 				if (!fcinfo->isnull && DatumGetBool(result))
 				{
-					*op->resvalue = (Datum) 0;
+					*op->resvalue = DummyDatum;
 					*op->resnull = true;
 
 					EEO_NEXT();
@@ -1587,7 +1587,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			 */
 			if (state->flags & op->d.returningexpr.nullflag)
 			{
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = DummyDatum;
 				*op->resnull = true;
 
 				EEO_JUMP(op->d.returningexpr.jumpdone);
@@ -1815,7 +1815,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			if (!fcinfo->args[0].isnull)
 				*op->resvalue = op->d.hashdatum.fn_addr(fcinfo);
 			else
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = DummyDatum;
 
 			*op->resnull = false;
 
@@ -1834,7 +1834,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 				 * finding a NULL.
 				 */
 				*op->resnull = true;
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = DummyDatum;
 				EEO_JUMP(op->d.hashdatum.jumpdone);
 			}
 
@@ -1882,7 +1882,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 				 * finding a NULL.
 				 */
 				*op->resnull = true;
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = DummyDatum;
 				EEO_JUMP(op->d.hashdatum.jumpdone);
 			}
 			else
@@ -2275,7 +2275,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 out_error:
 	pg_unreachable();
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -2602,7 +2602,7 @@ ExecJustAssignVarImpl(ExprState *state, TupleTableSlot *inslot, bool *isnull)
 	Assert(resultnum >= 0 && resultnum < outslot->tts_tupleDescriptor->natts);
 	outslot->tts_values[resultnum] =
 		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
-	return 0;
+	return DummyDatum;
 }
 
 /* Evaluate inner Var and assign to appropriate column of result tuple */
@@ -2655,7 +2655,7 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
 		if (args[argno].isnull)
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 	}
 	fcinfo->isnull = false;
@@ -2736,7 +2736,7 @@ ExecJustAssignVarVirtImpl(ExprState *state, TupleTableSlot *inslot, bool *isnull
 	outslot->tts_values[resultnum] = inslot->tts_values[attnum];
 	outslot->tts_isnull[resultnum] = inslot->tts_isnull[attnum];
 
-	return 0;
+	return DummyDatum;
 }
 
 /* Like ExecJustAssignInnerVar, optimized for virtual slots */
@@ -2817,7 +2817,7 @@ ExecJustHashVarImpl(ExprState *state, TupleTableSlot *slot, bool *isnull)
 	if (!fcinfo->args[0].isnull)
 		return hashop->d.hashdatum.fn_addr(fcinfo);
 	else
-		return (Datum) 0;
+		return DummyDatum;
 }
 
 /* implementation for hashing an outer Var */
@@ -2851,7 +2851,7 @@ ExecJustHashVarVirtImpl(ExprState *state, TupleTableSlot *slot, bool *isnull)
 	if (!fcinfo->args[0].isnull)
 		return hashop->d.hashdatum.fn_addr(fcinfo);
 	else
-		return (Datum) 0;
+		return DummyDatum;
 }
 
 /* Like ExecJustHashInnerVar, optimized for virtual slots */
@@ -2898,7 +2898,7 @@ ExecJustHashOuterVarStrict(ExprState *state, ExprContext *econtext,
 	{
 		/* return NULL on NULL input */
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 }
 
@@ -3176,7 +3176,7 @@ ExecEvalCoerceViaIOSafe(ExprState *state, ExprEvalStep *op)
 		if (SOFT_ERROR_OCCURRED(fcinfo_in->context))
 		{
 			*op->resnull = true;
-			*op->resvalue = (Datum) 0;
+			*op->resvalue = DummyDatum;
 			return;
 		}
 
@@ -4104,7 +4104,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
 		/* Get array element, checking for NULL */
 		if (bitmap && (*bitmap & bitmask) == 0)
 		{
-			fcinfo->args[1].value = (Datum) 0;
+			fcinfo->args[1].value = DummyDatum;
 			fcinfo->args[1].isnull = true;
 		}
 		else
@@ -4120,7 +4120,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
 		if (fcinfo->args[1].isnull && strictfunc)
 		{
 			fcinfo->isnull = true;
-			thisresult = (Datum) 0;
+			thisresult = DummyDatum;
 		}
 		else
 		{
@@ -4368,7 +4368,7 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
 			 * We have nulls in the array so a non-null lhs and no match must
 			 * yield NULL.
 			 */
-			result = (Datum) 0;
+			result = DummyDatum;
 			resultnull = true;
 		}
 		else
@@ -4382,7 +4382,7 @@ ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op, ExprContext *eco
 			 */
 			fcinfo->args[0].value = scalar;
 			fcinfo->args[0].isnull = scalar_isnull;
-			fcinfo->args[1].value = (Datum) 0;
+			fcinfo->args[1].value = DummyDatum;
 			fcinfo->args[1].isnull = true;
 
 			result = op->d.hashedscalararrayop.finfo->fn_addr(fcinfo);
@@ -4445,7 +4445,7 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
 	Datum		value;
 
 	*op->resnull = true;		/* until we get a result */
-	*op->resvalue = (Datum) 0;
+	*op->resvalue = DummyDatum;
 
 	switch (xexpr->op)
 	{
@@ -4684,7 +4684,7 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
 	{
 		if (jcstate->arg_nulls[0])
 		{
-			res = (Datum) 0;
+			res = DummyDatum;
 			isnull = true;
 		}
 		else
@@ -4704,7 +4704,7 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
 	{
 		if (jcstate->arg_nulls[0])
 		{
-			res = (Datum) 0;
+			res = DummyDatum;
 			isnull = true;
 		}
 		else
@@ -4895,7 +4895,7 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
 				if (jbv == NULL)
 				{
 					/* Will be coerced with json_populate_type(), if needed. */
-					*op->resvalue = (Datum) 0;
+					*op->resvalue = DummyDatum;
 					*op->resnull = true;
 				}
 				else if (!error && !empty)
@@ -4972,7 +4972,7 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
 	/* Handle ON EMPTY. */
 	if (empty)
 	{
-		*op->resvalue = (Datum) 0;
+		*op->resvalue = DummyDatum;
 		*op->resnull = true;
 		if (jsexpr->on_empty)
 		{
@@ -5015,7 +5015,7 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
 	if (error)
 	{
 		Assert(!throw_error);
-		*op->resvalue = (Datum) 0;
+		*op->resvalue = DummyDatum;
 		*op->resnull = true;
 		jsestate->error.value = BoolGetDatum(true);
 		/* Set up to catch coercion errors of the ON ERROR value. */
@@ -5137,7 +5137,7 @@ ExecEvalJsonCoercion(ExprState *state, ExprEvalStep *op,
 								   (Node *) escontext))
 			{
 				*op->resnull = true;
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = DummyDatum;
 			}
 			else
 				*op->resvalue = DirectFunctionCall1(bool_int4, *op->resvalue);
@@ -5218,7 +5218,7 @@ ExecEvalJsonCoercionFinish(ExprState *state, ExprEvalStep *op)
 							GetJsonBehaviorValueString(jsestate->jsexpr->on_empty)),
 					 errdetail("%s", jsestate->escontext.error_data->message)));
 
-		*op->resvalue = (Datum) 0;
+		*op->resvalue = DummyDatum;
 		*op->resnull = true;
 
 		jsestate->error.value = BoolGetDatum(true);
@@ -5368,7 +5368,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 				case VAR_RETURNING_OLD:
 					if (state->flags & EEO_FLAG_OLD_IS_NULL)
 					{
-						*op->resvalue = (Datum) 0;
+						*op->resvalue = DummyDatum;
 						*op->resnull = true;
 						return;
 					}
@@ -5378,7 +5378,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 				case VAR_RETURNING_NEW:
 					if (state->flags & EEO_FLAG_NEW_IS_NULL)
 					{
-						*op->resvalue = (Datum) 0;
+						*op->resvalue = DummyDatum;
 						*op->resnull = true;
 						return;
 					}
@@ -5593,7 +5593,7 @@ ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
 		(op->d.var.varreturningtype == VAR_RETURNING_NEW &&
 		 state->flags & EEO_FLAG_NEW_IS_NULL))
 	{
-		*op->resvalue = (Datum) 0;
+		*op->resvalue = DummyDatum;
 		*op->resnull = true;
 		return;
 	}
@@ -5670,7 +5670,7 @@ ExecAggCopyTransValue(AggState *aggstate, AggStatePerTrans pertrans,
 					  Datum newValue, bool newValueIsNull,
 					  Datum oldValue, bool oldValueIsNull)
 {
-	Assert(newValue != oldValue);
+	Assert(newValue.value != oldValue.value);
 
 	if (!newValueIsNull)
 	{
@@ -5692,7 +5692,7 @@ ExecAggCopyTransValue(AggState *aggstate, AggStatePerTrans pertrans,
 		 * callers can safely compare newValue/oldValue without having to
 		 * check their respective nullness.
 		 */
-		newValue = (Datum) 0;
+		newValue = DummyDatum;
 	}
 
 	if (!oldValueIsNull)
@@ -5743,7 +5743,7 @@ ExecEvalPreOrderedDistinctSingle(AggState *aggstate, AggStatePerTrans pertrans)
 			MemoryContextSwitchTo(oldContext);
 		}
 		else
-			pertrans->lastdatum = (Datum) 0;
+			pertrans->lastdatum = DummyDatum;
 		pertrans->lastisnull = isnull;
 		return true;
 	}
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 3f196de1ad2..00865616f19 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -287,7 +287,7 @@ ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
 
 		if (j == 0)
 		{
-			values[i] = (Datum) 0;
+			values[i] = DummyDatum;
 			isnull[i] = true;
 		}
 		else
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index a03fe780a02..4ac4f9035c5 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -554,7 +554,7 @@ ExecMakeFunctionResultSet(SetExprState *fcache,
 		fcache->funcResultStore = NULL;
 		*isDone = ExprEndResult;
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	/*
@@ -631,7 +631,7 @@ ExecMakeFunctionResultSet(SetExprState *fcache,
 	else
 	{
 		/* for a strict SRF, result for NULL is an empty set */
-		result = (Datum) 0;
+		result = DummyDatum;
 		*isNull = true;
 		*isDone = ExprEndResult;
 	}
@@ -677,7 +677,7 @@ ExecMakeFunctionResultSet(SetExprState *fcache,
 		/* if setResult was left null, treat it as empty set */
 		*isDone = ExprEndResult;
 		*isNull = true;
-		result = (Datum) 0;
+		result = DummyDatum;
 	}
 	else
 		ereport(ERROR,
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 8e02d68824f..78b4f741a9c 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -146,7 +146,7 @@ tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("cannot retrieve a system column in this context")));
 
-	return 0;					/* silence compiler warnings */
+	return DummyDatum;					/* silence compiler warnings */
 }
 
 /*
@@ -563,7 +563,7 @@ tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("cannot retrieve a system column in this context")));
 
-	return 0;					/* silence compiler warnings */
+	return DummyDatum;					/* silence compiler warnings */
 }
 
 /*
@@ -1036,7 +1036,7 @@ slot_deform_heap_tuple_internal(TupleTableSlot *slot, HeapTuple tuple,
 
 		if (hasnulls && att_isnull(attnum, bp))
 		{
-			values[attnum] = (Datum) 0;
+			values[attnum] = DummyDatum;
 			isnull[attnum] = true;
 			if (!slow)
 			{
@@ -2354,7 +2354,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
 		else
 		{
 			/* Handle dropped attributes by setting to NULL */
-			dvalues[i] = (Datum) 0;
+			dvalues[i] = DummyDatum;
 			nulls[i] = true;
 		}
 	}
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index fdc65c2b42b..f54f66ae5af 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -268,10 +268,10 @@ CreateExprContextInternal(EState *estate, Size minContextSize,
 	econtext->ecxt_aggvalues = NULL;
 	econtext->ecxt_aggnulls = NULL;
 
-	econtext->caseValue_datum = (Datum) 0;
+	econtext->caseValue_datum = DummyDatum;
 	econtext->caseValue_isNull = true;
 
-	econtext->domainValue_datum = (Datum) 0;
+	econtext->domainValue_datum = DummyDatum;
 	econtext->domainValue_isNull = true;
 
 	econtext->ecxt_estate = estate;
@@ -382,10 +382,10 @@ CreateStandaloneExprContext(void)
 	econtext->ecxt_aggvalues = NULL;
 	econtext->ecxt_aggnulls = NULL;
 
-	econtext->caseValue_datum = (Datum) 0;
+	econtext->caseValue_datum = DummyDatum;
 	econtext->caseValue_isNull = true;
 
-	econtext->domainValue_datum = (Datum) 0;
+	econtext->domainValue_datum = DummyDatum;
 	econtext->domainValue_isNull = true;
 
 	econtext->ecxt_estate = NULL;
@@ -997,7 +997,7 @@ UnregisterExprContextCallback(ExprContext *econtext,
 
 	while ((ecxt_callback = *prev_callback) != NULL)
 	{
-		if (ecxt_callback->function == function && ecxt_callback->arg == arg)
+		if (ecxt_callback->function == function && ecxt_callback->arg.value == arg.value)
 		{
 			*prev_callback = ecxt_callback->next;
 			pfree(ecxt_callback);
@@ -1078,7 +1078,7 @@ GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
 	{
 		/* Kinda bogus but compatible with old behavior... */
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	tupType = HeapTupleHeaderGetTypeId(tuple);
@@ -1141,7 +1141,7 @@ GetAttributeByNum(HeapTupleHeader tuple,
 	{
 		/* Kinda bogus but compatible with old behavior... */
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	tupType = HeapTupleHeaderGetTypeId(tuple);
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 359aafea681..0414316e796 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -1773,7 +1773,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 			rsi->isDone = ExprEndResult;
 
 			fcinfo->isnull = true;
-			result = (Datum) 0;
+			result = DummyDatum;
 
 			/* Deregister shutdown callback, if we made one */
 			if (fcache->shutdown_reg)
@@ -1804,7 +1804,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 				rsi->setDesc = CreateTupleDescCopy(fcache->junkFilter->jf_cleanTupType);
 
 			fcinfo->isnull = true;
-			result = (Datum) 0;
+			result = DummyDatum;
 
 			/* Deregister shutdown callback, if we made one */
 			if (fcache->shutdown_reg)
@@ -1830,7 +1830,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 			else
 			{
 				fcinfo->isnull = true;
-				result = (Datum) 0;
+				result = DummyDatum;
 			}
 		}
 		else
@@ -1838,7 +1838,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 			/* Should only get here for VOID functions and procedures */
 			Assert(fcache->func->rettype == VOIDOID);
 			fcinfo->isnull = true;
-			result = (Datum) 0;
+			result = DummyDatum;
 		}
 	}
 
@@ -2347,7 +2347,7 @@ check_sql_stmt_retval(List *queryTreeList,
 												   -1,
 												   InvalidOid,
 												   sizeof(int32),
-												   (Datum) 0,
+												   DummyDatum,
 												   true,	/* isnull */
 												   true /* byval */ );
 					upper_tlist = lappend(upper_tlist,
@@ -2393,7 +2393,7 @@ check_sql_stmt_retval(List *queryTreeList,
 											   -1,
 											   InvalidOid,
 											   sizeof(int32),
-											   (Datum) 0,
+											   DummyDatum,
 											   true,	/* isnull */
 											   true /* byval */ );
 				upper_tlist = lappend(upper_tlist,
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 377e016d732..6f86d9f1c16 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -848,14 +848,14 @@ process_ordered_aggregate_single(AggState *aggstate,
 								 AggStatePerTrans pertrans,
 								 AggStatePerGroup pergroupstate)
 {
-	Datum		oldVal = (Datum) 0;
+	Datum		oldVal = DummyDatum;
 	bool		oldIsNull = true;
 	bool		haveOldVal = false;
 	MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
 	MemoryContext oldContext;
 	bool		isDistinct = (pertrans->numDistinctCols > 0);
-	Datum		newAbbrevVal = (Datum) 0;
-	Datum		oldAbbrevVal = (Datum) 0;
+	Datum		newAbbrevVal = DummyDatum;
+	Datum		oldAbbrevVal = DummyDatum;
 	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
 	Datum	   *newVal;
 	bool	   *isNull;
@@ -891,7 +891,7 @@ process_ordered_aggregate_single(AggState *aggstate,
 			haveOldVal &&
 			((oldIsNull && *isNull) ||
 			 (!oldIsNull && !*isNull &&
-			  oldAbbrevVal == newAbbrevVal &&
+			  oldAbbrevVal.value == newAbbrevVal.value &&
 			  DatumGetBool(FunctionCall2Coll(&pertrans->equalfnOne,
 											 pertrans->aggCollation,
 											 oldVal, *newVal)))))
@@ -955,8 +955,8 @@ process_ordered_aggregate_multi(AggState *aggstate,
 	TupleTableSlot *slot2 = pertrans->uniqslot;
 	int			numTransInputs = pertrans->numTransInputs;
 	int			numDistinctCols = pertrans->numDistinctCols;
-	Datum		newAbbrevVal = (Datum) 0;
-	Datum		oldAbbrevVal = (Datum) 0;
+	Datum		newAbbrevVal = DummyDatum;
+	Datum		oldAbbrevVal = DummyDatum;
 	bool		haveOldValue = false;
 	TupleTableSlot *save = aggstate->tmpcontext->ecxt_outertuple;
 	int			i;
@@ -977,7 +977,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
 
 		if (numDistinctCols == 0 ||
 			!haveOldValue ||
-			newAbbrevVal != oldAbbrevVal ||
+			newAbbrevVal.value != oldAbbrevVal.value ||
 			!ExecQual(pertrans->equalfnMulti, tmpcontext))
 		{
 			/*
@@ -1100,7 +1100,7 @@ finalize_aggregate(AggState *aggstate,
 		/* Fill any remaining argument positions with nulls */
 		for (; i < numFinalArgs; i++)
 		{
-			fcinfo->args[i].value = (Datum) 0;
+			fcinfo->args[i].value = DummyDatum;
 			fcinfo->args[i].isnull = true;
 			anynull = true;
 		}
@@ -1108,7 +1108,7 @@ finalize_aggregate(AggState *aggstate,
 		if (fcinfo->flinfo->fn_strict && anynull)
 		{
 			/* don't call a strict function with NULL inputs */
-			*resultVal = (Datum) 0;
+			*resultVal = DummyDatum;
 			*resultIsNull = true;
 		}
 		else
@@ -1161,7 +1161,7 @@ finalize_partialaggregate(AggState *aggstate,
 		/* Don't call a strict serialization function with NULL input. */
 		if (pertrans->serialfn.fn_strict && pergroupstate->transValueIsNull)
 		{
-			*resultVal = (Datum) 0;
+			*resultVal = DummyDatum;
 			*resultIsNull = true;
 		}
 		else
@@ -1334,7 +1334,7 @@ finalize_aggregates(AggState *aggstate,
 					pfree(DatumGetPointer(pertrans->lastdatum));
 
 				pertrans->lastisnull = false;
-				pertrans->lastdatum = (Datum) 0;
+				pertrans->lastdatum = DummyDatum;
 			}
 			else
 				ExecClearTuple(pertrans->uniqslot);
@@ -3970,7 +3970,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 										  Anum_pg_aggregate_agginitval,
 										  &initValueIsNull);
 			if (initValueIsNull)
-				initValue = (Datum) 0;
+				initValue = DummyDatum;
 			else
 				initValue = GetAggInitVal(textInitVal, aggtranstype);
 
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 644363582d9..f4b5ae4a53b 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -196,7 +196,7 @@ FunctionNext(FunctionScanState *node)
 			 */
 			for (i = 0; i < fs->colcount; i++)
 			{
-				scanslot->tts_values[att] = (Datum) 0;
+				scanslot->tts_values[att] = DummyDatum;
 				scanslot->tts_isnull[att] = true;
 				att++;
 			}
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 7fcaa37fe62..2d0abfe6820 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -479,7 +479,7 @@ reorderqueue_push(IndexScanState *node, TupleTableSlot *slot,
 										   node->iss_OrderByTypByVals[i],
 										   node->iss_OrderByTypLens[i]);
 		else
-			rt->orderbyvals[i] = (Datum) 0;
+			rt->orderbyvals[i] = DummyDatum;
 		rt->orderbynulls[i] = orderbynulls[i];
 	}
 	pairingheap_add(node->iss_ReorderQueue, &rt->ph_node);
@@ -1293,7 +1293,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 				runtime_keys[n_runtime_keys].key_toastable =
 					TypeIsToastable(op_righttype);
 				n_runtime_keys++;
-				scanvalue = (Datum) 0;
+				scanvalue = DummyDatum;
 			}
 
 			/*
@@ -1417,7 +1417,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 					runtime_keys[n_runtime_keys].key_toastable =
 						TypeIsToastable(op_righttype);
 					n_runtime_keys++;
-					scanvalue = (Datum) 0;
+					scanvalue = DummyDatum;
 				}
 
 				/*
@@ -1541,7 +1541,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 					 */
 					runtime_keys[n_runtime_keys].key_toastable = true;
 					n_runtime_keys++;
-					scanvalue = (Datum) 0;
+					scanvalue = DummyDatum;
 				}
 			}
 			else
@@ -1552,7 +1552,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 					ExecInitExpr(rightop, planstate);
 				/* the remaining fields were zeroed by palloc0 */
 				n_array_keys++;
-				scanvalue = (Datum) 0;
+				scanvalue = DummyDatum;
 			}
 
 			/*
@@ -1616,7 +1616,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 								   InvalidOid,	/* no strategy subtype */
 								   InvalidOid,	/* no collation */
 								   InvalidOid,	/* no reg proc for this */
-								   (Datum) 0);	/* constant */
+								   DummyDatum);	/* constant */
 		}
 		else
 			elog(ERROR, "unsupported indexqual type: %d",
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 880f39fb2ff..c3bb01566a9 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -170,7 +170,7 @@ ExecProjectSRF(ProjectSetState *node, bool continuing)
 			 * If we're continuing to project output rows from a source tuple,
 			 * return NULLs once the SRF has been exhausted.
 			 */
-			*result = (Datum) 0;
+			*result = DummyDatum;
 			*isnull = true;
 			hassrf = true;
 		}
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index f7f6fc2da0b..e8579e8ab6c 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -467,7 +467,7 @@ ExecScanSubPlan(SubPlanState *node,
 		if (subLinkType == EXPR_SUBLINK ||
 			subLinkType == ROWCOMPARE_SUBLINK)
 		{
-			result = (Datum) 0;
+			result = DummyDatum;
 			*isNull = true;
 		}
 		else if (subLinkType == MULTIEXPR_SUBLINK)
@@ -480,7 +480,7 @@ ExecScanSubPlan(SubPlanState *node,
 
 				prmdata = &(econtext->ecxt_param_exec_vals[paramid]);
 				Assert(prmdata->execPlan == NULL);
-				prmdata->value = (Datum) 0;
+				prmdata->value = DummyDatum;
 				prmdata->isnull = true;
 			}
 		}
@@ -1219,7 +1219,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 		 * to avoid leaking memory across repeated calls, we have to remember
 		 * the latest value, much as for curTuple above.
 		 */
-		if (node->curArray != PointerGetDatum(NULL))
+		if (DatumGetPointer(node->curArray) != NULL)
 			pfree(DatumGetPointer(node->curArray));
 		node->curArray = makeArrayResultAny(astate,
 											econtext->ecxt_per_query_memory,
@@ -1249,7 +1249,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 				ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
 
 				prm->execPlan = NULL;
-				prm->value = (Datum) 0;
+				prm->value = DummyDatum;
 				prm->isnull = true;
 			}
 		}
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 9a1acce2b5d..fd4805806fb 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -230,7 +230,7 @@ initialize_windowaggregate(WindowAggState *winstate,
 	}
 	peraggstate->transValueIsNull = peraggstate->initValueIsNull;
 	peraggstate->transValueCount = 0;
-	peraggstate->resultValue = (Datum) 0;
+	peraggstate->resultValue = DummyDatum;
 	peraggstate->resultValueIsNull = true;
 }
 
@@ -612,7 +612,7 @@ finalize_windowaggregate(WindowAggState *winstate,
 		/* Fill any remaining argument positions with nulls */
 		for (i = 1; i < numFinalArgs; i++)
 		{
-			fcinfo->args[i].value = (Datum) 0;
+			fcinfo->args[i].value = DummyDatum;
 			fcinfo->args[i].isnull = true;
 			anynull = true;
 		}
@@ -620,7 +620,7 @@ finalize_windowaggregate(WindowAggState *winstate,
 		if (fcinfo->flinfo->fn_strict && anynull)
 		{
 			/* don't call a strict function with NULL inputs */
-			*result = (Datum) 0;
+			*result = DummyDatum;
 			*isnull = true;
 		}
 		else
@@ -896,7 +896,7 @@ eval_windowaggregates(WindowAggState *winstate)
 		{
 			if (!peraggstate->resulttypeByVal)
 				pfree(DatumGetPointer(peraggstate->resultValue));
-			peraggstate->resultValue = (Datum) 0;
+			peraggstate->resultValue = DummyDatum;
 			peraggstate->resultValueIsNull = true;
 		}
 	}
@@ -2366,7 +2366,7 @@ ExecWindowAgg(PlanState *pstate)
 					numfuncs = winstate->numfuncs;
 					for (i = 0; i < numfuncs; i++)
 					{
-						econtext->ecxt_aggvalues[i] = (Datum) 0;
+						econtext->ecxt_aggvalues[i] = DummyDatum;
 						econtext->ecxt_aggnulls[i] = true;
 					}
 
@@ -3020,7 +3020,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
 								  &peraggstate->initValueIsNull);
 
 	if (peraggstate->initValueIsNull)
-		peraggstate->initValue = (Datum) 0;
+		peraggstate->initValue = DummyDatum;
 	else
 		peraggstate->initValue = GetAggInitVal(textInitVal,
 											   aggtranstype);
@@ -3413,7 +3413,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
 		if (isout)
 			*isout = true;
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	else
 	{
@@ -3639,7 +3639,7 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno,
 	if (isout)
 		*isout = true;
 	*isnull = true;
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index ecb2e4ccaa1..098e6aa3ac9 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1258,7 +1258,7 @@ SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
 	{
 		SPI_result = SPI_ERROR_NOATTRIBUTE;
 		*isnull = true;
-		return (Datum) NULL;
+		return DummyDatum;
 	}
 
 	return heap_getattr(tuple, fnumber, tupdesc, isnull);
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index a57e59f27ea..d0853a91ed8 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -548,14 +548,14 @@ pg_options_to_table(PG_FUNCTION_ARGS)
 		}
 		else
 		{
-			values[1] = (Datum) 0;
+			values[1] = DummyDatum;
 			nulls[1] = true;
 		}
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
 							 values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 46511624f01..ec2a536e820 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -900,7 +900,7 @@ llvm_session_initialize(void)
 		opt3_tm = 0;
 	}
 
-	on_proc_exit(llvm_shutdown, 0);
+	on_proc_exit(llvm_shutdown, DummyDatum);
 
 	llvm_session_initialized = true;
 
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 890bcb0b0a7..b481be14482 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -650,7 +650,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_constvalue,
 								v_constnull;
 
-					v_constvalue = l_sizet_const(op->d.constval.value);
+					v_constvalue = l_sizet_const(op->d.constval.value.value);
 					v_constnull = l_sbool_const(op->d.constval.isnull);
 
 					LLVMBuildStore(b, v_constvalue, v_resvaluep);
@@ -2014,7 +2014,7 @@ llvm_compile_expr(ExprState *state)
 				{
 					LLVMValueRef v_initvalue;
 
-					v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value);
+					v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value.value);
 
 					LLVMBuildStore(b, v_initvalue, v_resvaluep);
 					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index e5171467de1..b6f1aceb2ad 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -283,7 +283,7 @@ pq_init(ClientSocket *client_sock)
 	PqCommReadingMsg = false;
 
 	/* set up process-exit hook to close the socket */
-	on_proc_exit(socket_close, 0);
+	on_proc_exit(socket_close, DummyDatum);
 
 	/*
 	 * In backends (as soon as forked) we operate the underlying socket in
diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c
index f1a08bc32ca..87baceb4397 100644
--- a/src/backend/libpq/pqmq.c
+++ b/src/backend/libpq/pqmq.c
@@ -56,7 +56,7 @@ pq_redirect_to_shm_mq(dsm_segment *seg, shm_mq_handle *mqh)
 	pq_mq_handle = mqh;
 	whereToSendOutput = DestRemote;
 	FrontendProtocol = PG_PROTOCOL_LATEST;
-	on_dsm_detach(seg, pq_cleanup_redirect_to_shm_mq, (Datum) 0);
+	on_dsm_detach(seg, pq_cleanup_redirect_to_shm_mq, DummyDatum);
 }
 
 /*
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index e2d9e9be41a..8663c37ed95 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -395,7 +395,7 @@ makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
 					 consttypmod,
 					 constcollid,
 					 (int) typLen,
-					 (Datum) 0,
+					 DummyDatum,
 					 true,
 					 typByVal);
 }
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 48b5d13b9b6..b781c16256e 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -621,7 +621,7 @@ readDatum(bool typbyval)
 	{
 		if (length > (Size) sizeof(Datum))
 			elog(ERROR, "byval datum but length = %zu", length);
-		res = (Datum) 0;
+		res = DummyDatum;
 		s = (char *) (&res);
 		for (i = 0; i < (Size) sizeof(Datum); i++)
 		{
@@ -630,7 +630,7 @@ readDatum(bool typbyval)
 		}
 	}
 	else if (length <= 0)
-		res = (Datum) NULL;
+		res = DummyDatum;
 	else
 	{
 		s = (char *) palloc(length);
diff --git a/src/backend/optimizer/prep/prepagg.c b/src/backend/optimizer/prep/prepagg.c
index c0a2f04a8c3..8068ecf8938 100644
--- a/src/backend/optimizer/prep/prepagg.c
+++ b/src/backend/optimizer/prep/prepagg.c
@@ -209,7 +209,7 @@ preprocess_aggref(Aggref *aggref, PlannerInfo *root)
 								  Anum_pg_aggregate_agginitval,
 								  &initValueIsNull);
 	if (initValueIsNull)
-		initValue = (Datum) 0;
+		initValue = DummyDatum;
 	else
 		initValue = GetAggInitVal(textInitVal, aggtranstype);
 
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index ffc9d6c3f30..71264165bc5 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -448,7 +448,7 @@ expand_insert_targetlist(PlannerInfo *root, List *tlist, Relation rel)
 											  -1,
 											  InvalidOid,
 											  sizeof(int32),
-											  (Datum) 0,
+											  DummyDatum,
 											  true, /* isnull */
 											  true /* byval */ );
 			}
@@ -463,7 +463,7 @@ expand_insert_targetlist(PlannerInfo *root, List *tlist, Relation rel)
 											  baseTypeMod,
 											  att_tup->attcollation,
 											  att_tup->attlen,
-											  (Datum) 0,
+											  DummyDatum,
 											  true, /* isnull */
 											  att_tup->attbyval);
 			}
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index ac28573cd0a..5caea86f576 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -2127,7 +2127,7 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
 		/* Arrange to flush cache on pg_amop changes */
 		CacheRegisterSyscacheCallback(AMOPOPID,
 									  InvalidateOprProofCacheCallBack,
-									  (Datum) 0);
+									  DummyDatum);
 	}
 
 	key.pred_op = pred_op;
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 0b5b81c7f27..acac11f1e9b 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -1284,7 +1284,7 @@ coerce_null_to_domain(Oid typid, int32 typmod, Oid collation,
 								baseTypeMod,
 								collation,
 								typlen,
-								(Datum) 0,
+								DummyDatum,
 								true,	/* isnull */
 								typbyval);
 	if (typid != baseTypeId)
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index d66276801c6..a74f8293bf5 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -4846,7 +4846,7 @@ transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior,
 static Node *
 GetJsonBehaviorConst(JsonBehaviorType btype, int location)
 {
-	Datum		val = (Datum) 0;
+	Datum		val = DummyDatum;
 	Oid			typid = JSONBOID;
 	int			len = -1;
 	bool		isbyval = false;
@@ -4880,7 +4880,7 @@ GetJsonBehaviorConst(JsonBehaviorType btype, int location)
 		case JSON_BEHAVIOR_NULL:
 		case JSON_BEHAVIOR_UNKNOWN:
 		case JSON_BEHAVIOR_EMPTY:
-			val = (Datum) 0;
+			val = DummyDatum;
 			isnull = true;
 			typid = INT4OID;
 			len = sizeof(int32);
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index d6feb16aef3..352285396bd 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -360,7 +360,7 @@ make_const(ParseState *pstate, A_Const *aconst)
 						-1,
 						InvalidOid,
 						-2,
-						(Datum) 0,
+						DummyDatum,
 						true,
 						false);
 		con->location = aconst->location;
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 0c4337563cf..15536a772f5 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -995,10 +995,10 @@ find_oper_cache_entry(OprCacheKey *key)
 		/* Arrange to flush cache on pg_operator and pg_cast changes */
 		CacheRegisterSyscacheCallback(OPERNAMENSP,
 									  InvalidateOprCacheCallBack,
-									  (Datum) 0);
+									  DummyDatum);
 		CacheRegisterSyscacheCallback(CASTSOURCETARGET,
 									  InvalidateOprCacheCallBack,
-									  (Datum) 0);
+									  DummyDatum);
 	}
 
 	/* Look for an existing entry */
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index afcf54169c3..9fca9e23bf8 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -2549,7 +2549,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 											   index_rel->rd_rel->relam);
 				if (indclass->values[i] != defopclass ||
 					attform->attcollation != index_rel->rd_indcollation[i] ||
-					attoptions != (Datum) 0 ||
+					attoptions.value != DummyDatum.value ||
 					index_rel->rd_indoption[i] != 0)
 					ereport(ERROR,
 							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 4bdc2941efb..801356097f9 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -940,8 +940,8 @@ partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval,
 		 */
 #ifdef USE_ASSERT_CHECKING
 		for (i = 0; i < b1->ndatums; i++)
-			Assert((b1->datums[i][0] == b2->datums[i][0] &&
-					b1->datums[i][1] == b2->datums[i][1]));
+			Assert((b1->datums[i][0].value == b2->datums[i][0].value &&
+					b1->datums[i][1].value == b2->datums[i][1].value));
 #endif
 	}
 	else
diff --git a/src/backend/port/posix_sema.c b/src/backend/port/posix_sema.c
index 269c7460817..7b3c78ab254 100644
--- a/src/backend/port/posix_sema.c
+++ b/src/backend/port/posix_sema.c
@@ -227,7 +227,7 @@ PGReserveSemaphores(int maxSemas)
 	maxSems = maxSemas;
 	nextSemKey = statbuf.st_ino;
 
-	on_shmem_exit(ReleaseSemaphores, 0);
+	on_shmem_exit(ReleaseSemaphores, DummyDatum);
 }
 
 /*
diff --git a/src/backend/port/sysv_sema.c b/src/backend/port/sysv_sema.c
index 423b2b4f9d6..f6b16b55ab6 100644
--- a/src/backend/port/sysv_sema.c
+++ b/src/backend/port/sysv_sema.c
@@ -341,7 +341,7 @@ PGReserveSemaphores(int maxSemas)
 	nextSemaKey = statbuf.st_ino;
 	nextSemaNumber = SEMAS_PER_SET; /* force sema set alloc on 1st call */
 
-	on_shmem_exit(ReleaseSemaphores, 0);
+	on_shmem_exit(ReleaseSemaphores, DummyDatum);
 }
 
 /*
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 197926d44f6..6c856efa60f 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -740,7 +740,7 @@ PGSharedMemoryCreate(Size size,
 		AnonymousShmemSize = size;
 
 		/* Register on-exit routine to unmap the anonymous segment */
-		on_shmem_exit(AnonymousShmemDetach, (Datum) 0);
+		on_shmem_exit(AnonymousShmemDetach, DummyDatum);
 
 		/* Now we need only allocate a minimal-sized SysV shmem block. */
 		sysvsize = sizeof(PGShmemHeader);
diff --git a/src/backend/port/win32_sema.c b/src/backend/port/win32_sema.c
index 5854ad1f54d..4ef1e469a75 100644
--- a/src/backend/port/win32_sema.c
+++ b/src/backend/port/win32_sema.c
@@ -52,7 +52,7 @@ PGReserveSemaphores(int maxSemas)
 	numSems = 0;
 	maxSems = maxSemas;
 
-	on_shmem_exit(ReleaseSemaphores, 0);
+	on_shmem_exit(ReleaseSemaphores, DummyDatum);
 }
 
 /*
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 9474095f271..97cd24c6106 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1537,7 +1537,7 @@ AutoVacWorkerMain(const void *startup_data, size_t startup_data_len)
 		AutoVacuumShmem->av_startingWorker = NULL;
 		LWLockRelease(AutovacuumLock);
 
-		on_shmem_exit(FreeWorkerInfo, 0);
+		on_shmem_exit(FreeWorkerInfo, DummyDatum);
 
 		/* wake up the launcher */
 		if (AutoVacuumShmem->av_launcherpid != 0)
diff --git a/src/backend/postmaster/auxprocess.c b/src/backend/postmaster/auxprocess.c
index a6d3630398f..22b84b21b3d 100644
--- a/src/backend/postmaster/auxprocess.c
+++ b/src/backend/postmaster/auxprocess.c
@@ -82,7 +82,7 @@ AuxiliaryProcessMainCommon(void)
 	pgstat_bestart_final();
 
 	/* register a before-shutdown callback for LWLock cleanup */
-	before_shmem_exit(ShutdownAuxiliaryProcess, 0);
+	before_shmem_exit(ShutdownAuxiliaryProcess, DummyDatum);
 
 	SetProcessingMode(NormalProcessing);
 }
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 8490148a47d..2c1b951ceb3 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -242,7 +242,7 @@ CheckpointerMain(const void *startup_data, size_t startup_data_len)
 	 * signal checkpointer to exit after all processes that could emit stats
 	 * have been shut down.
 	 */
-	before_shmem_exit(pgstat_before_server_shutdown, 0);
+	before_shmem_exit(pgstat_before_server_shutdown, DummyDatum);
 
 	/*
 	 * Create a memory context that we will do all our work in.  We do this so
@@ -612,7 +612,7 @@ CheckpointerMain(const void *startup_data, size_t startup_data_len)
 		 * out pending statistic.
 		 */
 		PendingCheckpointerStats.num_requested++;
-		ShutdownXLOG(0, 0);
+		ShutdownXLOG(0, DummyDatum);
 		pgstat_report_checkpointer();
 		pgstat_report_wal(true);
 
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 78e39e5f866..105fedabb62 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -245,7 +245,7 @@ PgArchiverMain(const void *startup_data, size_t startup_data_len)
 	Assert(XLogArchivingActive());
 
 	/* Arrange to clean up at archiver exit */
-	on_shmem_exit(pgarch_die, 0);
+	on_shmem_exit(pgarch_die, DummyDatum);
 
 	/*
 	 * Advertise our proc number so that backends can use our latch to wake us
@@ -945,7 +945,7 @@ LoadArchiveLibrary(void)
 	if (ArchiveCallbacks->startup_cb != NULL)
 		ArchiveCallbacks->startup_cb(archive_module_state);
 
-	before_shmem_exit(pgarch_call_module_shutdown_cb, 0);
+	before_shmem_exit(pgarch_call_module_shutdown_cb, DummyDatum);
 }
 
 /*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index e01d9f0cfe8..98240a99fc1 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1109,7 +1109,7 @@ PostmasterMain(int argc, char *argv[])
 	 * sockets again at postmaster shutdown.
 	 */
 	ListenSockets = palloc(MAXLISTEN * sizeof(pgsocket));
-	on_proc_exit(CloseServerPorts, 0);
+	on_proc_exit(CloseServerPorts, DummyDatum);
 
 	if (ListenAddresses)
 	{
@@ -1308,7 +1308,7 @@ PostmasterMain(int argc, char *argv[])
 			write_stderr("%s: could not write external PID file \"%s\": %m\n",
 						 progname, external_pid_file);
 
-		on_proc_exit(unlink_external_pid_file, 0);
+		on_proc_exit(unlink_external_pid_file, DummyDatum);
 	}
 
 	/*
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c
index 27e86cf393f..1df0ff6711e 100644
--- a/src/backend/postmaster/startup.c
+++ b/src/backend/postmaster/startup.c
@@ -221,7 +221,7 @@ StartupProcessMain(const void *startup_data, size_t startup_data_len)
 	AuxiliaryProcessMainCommon();
 
 	/* Arrange to clean up at startup process exit */
-	on_shmem_exit(StartupProcExit, 0);
+	on_shmem_exit(StartupProcExit, DummyDatum);
 
 	/*
 	 * Properly accept or ignore signals the postmaster might send us.
diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c
index 777c9a8d555..386a23eecb3 100644
--- a/src/backend/postmaster/walsummarizer.c
+++ b/src/backend/postmaster/walsummarizer.c
@@ -256,7 +256,7 @@ WalSummarizerMain(const void *startup_data, size_t startup_data_len)
 	pqsignal(SIGUSR2, SIG_IGN); /* not used */
 
 	/* Advertise ourselves. */
-	on_shmem_exit(WalSummarizerShutdown, (Datum) 0);
+	on_shmem_exit(WalSummarizerShutdown, DummyDatum);
 	LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
 	WalSummarizerCtl->summarizer_pgprocno = MyProcNumber;
 	LWLockRelease(WALSummarizerLock);
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index 1fa931a7422..6c40a466744 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -964,7 +964,7 @@ ParallelApplyWorkerMain(Datum main_arg)
 	 */
 	CacheRegisterSyscacheCallback(SUBSCRIPTIONRELMAP,
 								  invalidate_syncing_table_states,
-								  (Datum) 0);
+								  DummyDatum);
 
 	set_apply_error_context_origin(originname);
 
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index 742d9ba68e9..a6223d25b70 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -752,7 +752,7 @@ logicalrep_worker_attach(int slot)
 	}
 
 	MyLogicalRepWorker->proc = MyProc;
-	before_shmem_exit(logicalrep_worker_onexit, (Datum) 0);
+	before_shmem_exit(logicalrep_worker_onexit, DummyDatum);
 
 	LWLockRelease(LogicalRepWorkerLock);
 }
@@ -962,7 +962,7 @@ ApplyLauncherRegister(void)
 			 "logical replication launcher");
 	bgw.bgw_restart_time = 5;
 	bgw.bgw_notify_pid = 0;
-	bgw.bgw_main_arg = (Datum) 0;
+	bgw.bgw_main_arg = DummyDatum;
 
 	RegisterBackgroundWorker(&bgw);
 }
@@ -1148,7 +1148,7 @@ ApplyLauncherMain(Datum main_arg)
 	ereport(DEBUG1,
 			(errmsg_internal("logical replication launcher started")));
 
-	before_shmem_exit(logicalrep_launcher_onexit, (Datum) 0);
+	before_shmem_exit(logicalrep_launcher_onexit, DummyDatum);
 
 	Assert(LogicalRepCtx->launcher_pid == 0);
 	LogicalRepCtx->launcher_pid = MyProcPid;
@@ -1606,5 +1606,5 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
 
 	LWLockRelease(LogicalRepWorkerLock);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index ca53caac2f2..9a6c382cc3b 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -321,7 +321,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
 	}
 	PG_END_TRY();
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index 87f10e50dcc..064a5bce49e 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -1125,7 +1125,7 @@ replorigin_session_setup(RepOriginId node, int acquired_by)
 
 	if (!registered_cleanup)
 	{
-		on_shmem_exit(ReplicationOriginExitCleanup, 0);
+		on_shmem_exit(ReplicationOriginExitCleanup, DummyDatum);
 		registered_cleanup = true;
 	}
 
@@ -1603,5 +1603,5 @@ pg_show_replication_origin_status(PG_FUNCTION_ARGS)
 
 #undef REPLICATION_ORIGIN_PROGRESS_COLS
 
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c
index f59046ad620..4e2e2520136 100644
--- a/src/backend/replication/logical/relation.c
+++ b/src/backend/replication/logical/relation.c
@@ -122,7 +122,7 @@ logicalrep_relmap_init(void)
 
 	/* Watch for invalidation events. */
 	CacheRegisterRelcacheCallback(logicalrep_relmap_invalidate_cb,
-								  (Datum) 0);
+								  DummyDatum);
 }
 
 /*
@@ -615,7 +615,7 @@ logicalrep_partmap_init(void)
 
 	/* Watch for invalidation events. */
 	CacheRegisterRelcacheCallback(logicalrep_partmap_invalidate_cb,
-								  (Datum) 0);
+								  DummyDatum);
 }
 
 /*
diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c
index 2f0c08b8fbd..93a51f50f31 100644
--- a/src/backend/replication/logical/slotsync.c
+++ b/src/backend/replication/logical/slotsync.c
@@ -1422,7 +1422,7 @@ ReplSlotSyncWorkerMain(const void *startup_data, size_t startup_data_len)
 	ereport(LOG, errmsg("slot sync worker started"));
 
 	/* Register it as soon as SlotSyncCtx->pid is initialized. */
-	before_shmem_exit(slotsync_worker_onexit, (Datum) 0);
+	before_shmem_exit(slotsync_worker_onexit, DummyDatum);
 
 	/*
 	 * Establishes SIGALRM handler and initialize timeout module. It is needed
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index b59221c4d06..74edd29821e 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -1040,7 +1040,7 @@ slot_store_data(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 				 * LOGICALREP_COLUMN_UNCHANGED here, but if we do, treat it as
 				 * NULL.)
 				 */
-				slot->tts_values[i] = (Datum) 0;
+				slot->tts_values[i] = DummyDatum;
 				slot->tts_isnull[i] = true;
 			}
 
@@ -1054,7 +1054,7 @@ slot_store_data(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 			 * (missing values should be later filled using
 			 * slot_fill_defaults).
 			 */
-			slot->tts_values[i] = (Datum) 0;
+			slot->tts_values[i] = DummyDatum;
 			slot->tts_isnull[i] = true;
 		}
 	}
@@ -1151,7 +1151,7 @@ slot_modify_data(TupleTableSlot *slot, TupleTableSlot *srcslot,
 			else
 			{
 				/* must be LOGICALREP_COLUMN_NULL */
-				slot->tts_values[i] = (Datum) 0;
+				slot->tts_values[i] = DummyDatum;
 				slot->tts_isnull[i] = true;
 			}
 
@@ -5106,7 +5106,7 @@ start_apply(XLogRecPtr origin_startpos)
 		 * transaction loss as that transaction won't be sent again by the
 		 * server.
 		 */
-		replorigin_reset(0, (Datum) 0);
+		replorigin_reset(0, DummyDatum);
 
 		if (MySubscription->disableonerr)
 			DisableSubscriptionAndExit();
@@ -5331,11 +5331,11 @@ InitializeLogRepWorker(void)
 	 */
 	CacheRegisterSyscacheCallback(SUBSCRIPTIONOID,
 								  subscription_change_cb,
-								  (Datum) 0);
+								  DummyDatum);
 
 	CacheRegisterSyscacheCallback(AUTHOID,
 								  subscription_change_cb,
-								  (Datum) 0);
+								  DummyDatum);
 
 	if (am_tablesync_worker())
 		ereport(LOG,
@@ -5400,7 +5400,7 @@ SetupApplyOrSyncWorker(int worker_slot)
 	 * state may process a shutdown signal before committing the current apply
 	 * operation. So, it is important to register such a callback here.
 	 */
-	before_shmem_exit(replorigin_reset, (Datum) 0);
+	before_shmem_exit(replorigin_reset, DummyDatum);
 
 	/* Connect to the origin and start the replication. */
 	elog(DEBUG1, "connecting to publisher using connection string \"%s\"",
@@ -5412,7 +5412,7 @@ SetupApplyOrSyncWorker(int worker_slot)
 	 */
 	CacheRegisterSyscacheCallback(SUBSCRIPTIONRELMAP,
 								  invalidate_syncing_table_states,
-								  (Datum) 0);
+								  DummyDatum);
 }
 
 /* Logical Replication Apply worker entry point */
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 80540c017bd..69a90ff5e32 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -535,9 +535,9 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 		{
 			CacheRegisterSyscacheCallback(PUBLICATIONOID,
 										  publication_invalidation_cb,
-										  (Datum) 0);
+										  DummyDatum);
 			CacheRegisterRelSyncCallback(rel_sync_cache_relation_cb,
-										 (Datum) 0);
+										 DummyDatum);
 			publication_callback_registered = true;
 		}
 
@@ -918,7 +918,7 @@ pgoutput_row_filter_init(PGOutputData *data, List *publications,
 	{
 		Publication *pub = lfirst(lc);
 		HeapTuple	rftuple = NULL;
-		Datum		rfdatum = 0;
+		Datum		rfdatum = DummyDatum;
 		bool		pub_no_filter = true;
 
 		/*
@@ -1973,7 +1973,7 @@ init_rel_sync_cache(MemoryContext cachectx)
 		return;
 
 	/* We must update the cache entry for a relation after a relcache flush */
-	CacheRegisterRelcacheCallback(rel_sync_cache_relation_cb, (Datum) 0);
+	CacheRegisterRelcacheCallback(rel_sync_cache_relation_cb, DummyDatum);
 
 	/*
 	 * Flush all cache entries after a pg_namespace change, in case it was a
@@ -1988,7 +1988,7 @@ init_rel_sync_cache(MemoryContext cachectx)
 	 */
 	CacheRegisterSyscacheCallback(NAMESPACEOID,
 								  rel_sync_cache_publication_cb,
-								  (Datum) 0);
+								  DummyDatum);
 
 	relation_callbacks_registered = true;
 }
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 8605776ad86..80a5b0efb2f 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -240,7 +240,7 @@ ReplicationSlotsShmemInit(void)
 void
 ReplicationSlotInitialize(void)
 {
-	before_shmem_exit(ReplicationSlotShmemExit, 0);
+	before_shmem_exit(ReplicationSlotShmemExit, DummyDatum);
 }
 
 /*
diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
index 69f4c6157c5..f7668f47e55 100644
--- a/src/backend/replication/slotfuncs.c
+++ b/src/backend/replication/slotfuncs.c
@@ -451,7 +451,7 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
 
 	LWLockRelease(ReplicationSlotControlLock);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index ee911394a23..29c8cbeca47 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -3054,7 +3054,7 @@ InitWalSenderSlot(void)
 	Assert(MyWalSnd != NULL);
 
 	/* Arrange to clean up at walsender exit */
-	on_shmem_exit(WalSndKill, 0);
+	on_shmem_exit(WalSndKill, DummyDatum);
 }
 
 /* Destroy the per-walsender data structure for this walsender process */
@@ -4113,7 +4113,7 @@ pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
 							 values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index e8241926d2c..0905801e01d 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_stats.c
@@ -404,7 +404,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 			set_stats_slot(values, nulls, replaces,
 						   STATISTIC_KIND_HISTOGRAM,
 						   lt_opr, atttypcoll,
-						   0, true, stavalues, false);
+						   DummyDatum, true, stavalues, false);
 		}
 		else
 			result = false;
@@ -420,7 +420,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 		set_stats_slot(values, nulls, replaces,
 					   STATISTIC_KIND_CORRELATION,
 					   lt_opr, atttypcoll,
-					   stanumbers, false, 0, true);
+					   stanumbers, false, DummyDatum, true);
 	}
 
 	/* STATISTIC_KIND_MCELEM */
@@ -455,7 +455,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 		set_stats_slot(values, nulls, replaces,
 					   STATISTIC_KIND_DECHIST,
 					   elem_eq_opr, atttypcoll,
-					   stanumbers, false, 0, true);
+					   stanumbers, false, DummyDatum, true);
 	}
 
 	/*
@@ -481,7 +481,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 			set_stats_slot(values, nulls, replaces,
 						   STATISTIC_KIND_BOUNDS_HISTOGRAM,
 						   InvalidOid, InvalidOid,
-						   0, true, stavalues, false);
+						   DummyDatum, true, stavalues, false);
 		}
 		else
 			result = false;
@@ -722,7 +722,7 @@ text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid,
 		escontext.error_data->elevel = WARNING;
 		ThrowErrorData(escontext.error_data);
 		*ok = false;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	if (array_contains_nulls(DatumGetArrayTypeP(result)))
@@ -731,7 +731,7 @@ text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("\"%s\" array cannot contain NULL values", staname)));
 		*ok = false;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*ok = true;
@@ -893,7 +893,7 @@ init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
 	/* initialize stakind, staop, and stacoll slots */
 	for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++)
 	{
-		values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0;
+		values[Anum_pg_statistic_stakind1 + slotnum - 1] = DummyDatum;
 		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;
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index 3e031cf831a..90e6e1302eb 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -155,7 +155,7 @@ BuildRelationExtStatistics(Relation onerel, bool inh, double totalrows,
 		MVNDistinct *ndistinct = NULL;
 		MVDependencies *dependencies = NULL;
 		MCVList    *mcv = NULL;
-		Datum		exprstats = (Datum) 0;
+		Datum		exprstats = DummyDatum;
 		VacAttrStats **stats;
 		ListCell   *lc2;
 		int			stattarget;
@@ -803,7 +803,7 @@ statext_store(Oid statOid, bool inh,
 		nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = (data == NULL);
 		values[Anum_pg_statistic_ext_data_stxdmcv - 1] = PointerGetDatum(data);
 	}
-	if (exprs != (Datum) 0)
+	if (exprs.value != DummyDatum.value)
 	{
 		nulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = false;
 		values[Anum_pg_statistic_ext_data_stxdexpr - 1] = exprs;
@@ -2180,7 +2180,7 @@ compute_expr_stats(Relation onerel, AnlExprData *exprdata, int nexprs,
 											  &isnull);
 			if (isnull)
 			{
-				exprvals[tcnt] = (Datum) 0;
+				exprvals[tcnt] = DummyDatum;
 				exprnulls[tcnt] = true;
 			}
 			else
@@ -2319,7 +2319,7 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
 		if (!stats->stats_valid)
 		{
 			astate = accumArrayResult(astate,
-									  (Datum) 0,
+									  DummyDatum,
 									  true,
 									  typOid,
 									  CurrentMemoryContext);
@@ -2374,7 +2374,7 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
 			else
 			{
 				nulls[i] = true;
-				values[i++] = (Datum) 0;
+				values[i++] = DummyDatum;
 			}
 		}
 		i = Anum_pg_statistic_stavalues1 - 1;
@@ -2395,7 +2395,7 @@ serialize_expr_stats(AnlExprData *exprdata, int nexprs)
 			else
 			{
 				nulls[i] = true;
-				values[i++] = (Datum) 0;
+				values[i++] = DummyDatum;
 			}
 		}
 
@@ -2613,7 +2613,7 @@ make_build_data(Relation rel, StatExtEntry *stat, int numrows, HeapTuple *rows,
 								 &isnull);
 			if (isnull)
 			{
-				result->values[idx][i] = (Datum) 0;
+				result->values[idx][i] = DummyDatum;
 				result->nulls[idx][i] = true;
 			}
 			else
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index f59fb821543..51d66870184 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -1188,7 +1188,7 @@ statext_mcv_deserialize(bytea *data)
 			/* for by-val types we simply copy data into the mapping */
 			for (i = 0; i < info[dim].nvalues; i++)
 			{
-				Datum		v = 0;
+				Datum		v = DummyDatum;
 
 				memcpy(&v, ptr, info[dim].typlen);
 				ptr += info[dim].typlen;
@@ -1433,7 +1433,7 @@ pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS)
 			}
 			else
 				astate_values = accumArrayResult(astate_values,
-												 (Datum) 0,
+												 DummyDatum,
 												 true,
 												 TEXTOID,
 												 CurrentMemoryContext);
diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c
index a9a3224efe6..c0c24032cf3 100644
--- a/src/backend/statistics/stat_utils.c
+++ b/src/backend/statistics/stat_utils.c
@@ -295,7 +295,7 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
 	/* clear positional args */
 	for (int i = 0; arginfo[i].argname != NULL; i++)
 	{
-		positional_fcinfo->args[i].value = (Datum) 0;
+		positional_fcinfo->args[i].value = DummyDatum;
 		positional_fcinfo->args[i].isnull = true;
 	}
 
diff --git a/src/backend/storage/aio/aio_funcs.c b/src/backend/storage/aio/aio_funcs.c
index b25f9204041..7c80ee50d5a 100644
--- a/src/backend/storage/aio/aio_funcs.c
+++ b/src/backend/storage/aio/aio_funcs.c
@@ -226,5 +226,5 @@ pg_get_aios(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/storage/aio/aio_init.c b/src/backend/storage/aio/aio_init.c
index 885c3940c66..7012105b13b 100644
--- a/src/backend/storage/aio/aio_init.c
+++ b/src/backend/storage/aio/aio_init.c
@@ -235,5 +235,5 @@ pgaio_init_backend(void)
 	if (pgaio_method_ops->init_backend)
 		pgaio_method_ops->init_backend();
 
-	before_shmem_exit(pgaio_shutdown, 0);
+	before_shmem_exit(pgaio_shutdown, DummyDatum);
 }
diff --git a/src/backend/storage/aio/method_worker.c b/src/backend/storage/aio/method_worker.c
index bf8f77e6ff6..0e90007c187 100644
--- a/src/backend/storage/aio/method_worker.c
+++ b/src/backend/storage/aio/method_worker.c
@@ -358,7 +358,7 @@ pgaio_worker_register(void)
 	io_worker_control->workers[MyIoWorkerId].latch = MyLatch;
 	LWLockRelease(AioWorkerSubmissionQueueLock);
 
-	on_shmem_exit(pgaio_worker_die, 0);
+	on_shmem_exit(pgaio_worker_die, DummyDatum);
 }
 
 static void
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index c50b4a2cd2f..61f4fffc0db 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -4033,7 +4033,7 @@ InitBufferManagerAccess(void)
 	 * the corresponding phase of backend shutdown.
 	 */
 	Assert(MyProc != NULL);
-	on_shmem_exit(AtProcExit_Buffers, 0);
+	on_shmem_exit(AtProcExit_Buffers, DummyDatum);
 }
 
 /*
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index a4ec7959f31..70b1613e349 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -936,7 +936,7 @@ InitTemporaryFileAccess(void)
 	 * Register before-shmem-exit hook to ensure temp files are dropped while
 	 * we can still report stats.
 	 */
-	before_shmem_exit(BeforeShmemExit_Files, 0);
+	before_shmem_exit(BeforeShmemExit_Files, DummyDatum);
 
 #ifdef USE_ASSERT_CHECKING
 	temporary_files_allowed = true;
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index f92a52a00e6..e14476997f8 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -1154,7 +1154,7 @@ cancel_on_dsm_detach(dsm_segment *seg, on_dsm_detach_callback function,
 		dsm_segment_detach_callback *cb;
 
 		cb = slist_container(dsm_segment_detach_callback, node, iter.cur);
-		if (cb->function == function && cb->arg == arg)
+		if (cb->function == function && cb->arg.value == arg.value)
 		{
 			slist_delete_current(&iter);
 			pfree(cb);
diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c
index 1682cc6d34c..afda1db9b5a 100644
--- a/src/backend/storage/ipc/dsm_registry.c
+++ b/src/backend/storage/ipc/dsm_registry.c
@@ -482,5 +482,5 @@ pg_get_dsm_registry_allocations(PG_FUNCTION_ARGS)
 	}
 	dshash_seq_term(&status);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c
index 567739b5be9..69057ce2c49 100644
--- a/src/backend/storage/ipc/ipc.c
+++ b/src/backend/storage/ipc/ipc.c
@@ -396,11 +396,11 @@ cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg)
 	if (before_shmem_exit_index > 0 &&
 		before_shmem_exit_list[before_shmem_exit_index - 1].function
 		== function &&
-		before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg)
+		before_shmem_exit_list[before_shmem_exit_index - 1].arg.value == arg.value)
 		--before_shmem_exit_index;
 	else
 		elog(ERROR, "before_shmem_exit callback (%p,0x%" PRIxPTR ") is not the latest entry",
-			 function, arg);
+			 function, arg.value);
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c
index f2ea01622f9..a78c5dbe18d 100644
--- a/src/backend/storage/ipc/pmsignal.c
+++ b/src/backend/storage/ipc/pmsignal.c
@@ -297,7 +297,7 @@ RegisterPostmasterChildActive(void)
 	PMSignalState->PMChildFlags[slot] = PM_CHILD_ACTIVE;
 
 	/* Arrange to clean up at exit. */
-	on_shmem_exit(MarkPostmasterChildInactive, 0);
+	on_shmem_exit(MarkPostmasterChildInactive, DummyDatum);
 }
 
 /*
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
index 087821311cc..7a76de115bc 100644
--- a/src/backend/storage/ipc/procsignal.c
+++ b/src/backend/storage/ipc/procsignal.c
@@ -216,7 +216,7 @@ ProcSignalInit(const uint8 *cancel_key, int cancel_key_len)
 	MyProcSignalSlot = slot;
 
 	/* Set up to release the slot on process exit */
-	on_shmem_exit(CleanupProcSignalState, (Datum) 0);
+	on_shmem_exit(CleanupProcSignalState, DummyDatum);
 }
 
 /*
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index d12a3ca0684..69777b92951 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -571,7 +571,7 @@ pg_get_shmem_allocations(PG_FUNCTION_ARGS)
 
 	LWLockRelease(ShmemIndexLock);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -725,7 +725,7 @@ pg_get_shmem_allocations_numa(PG_FUNCTION_ARGS)
 	LWLockRelease(ShmemIndexLock);
 	firstNumaTouch = false;
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 /*
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index c07fb588355..cc35993aebc 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -292,6 +292,8 @@
 #define SxactIsROUnsafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0)
 #define SxactIsPartiallyReleased(sxact) (((sxact)->flags & SXACT_FLAG_PARTIALLY_RELEASED) != 0)
 
+static HTAB *PredicateLockTargetHash; // XXX
+
 /*
  * Compute the hash code associated with a PREDICATELOCKTARGETTAG.
  *
@@ -300,8 +302,11 @@
  * passing the hashcode to hash_search_with_hash_value(), we can extract
  * the lock partition number from the hashcode.
  */
-#define PredicateLockTargetTagHashCode(predicatelocktargettag) \
-	get_hash_value(PredicateLockTargetHash, predicatelocktargettag)
+static inline uint32
+PredicateLockTargetTagHashCode(const PREDICATELOCKTARGETTAG *predicatelocktargettag)
+{
+	return get_hash_value(PredicateLockTargetHash, predicatelocktargettag);
+}
 
 /*
  * Given a predicate lock tag, and the hash for its target,
@@ -313,9 +318,12 @@
  * don't care if we lose high-order bits of the address; use an
  * intermediate variable to suppress cast-pointer-to-int warnings.
  */
-#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash) \
-	((targethash) ^ ((uint32) PointerGetDatum((predicatelocktag)->myXact)) \
-	 << LOG2_NUM_PREDICATELOCK_PARTITIONS)
+static inline uint32
+PredicateLockHashCodeFromTargetHashCode(const PREDICATELOCKTAG *predicatelocktag, uint32 targethash)
+{
+	return (targethash ^ DatumGetUInt32(PointerGetDatum(predicatelocktag->myXact))
+			<< LOG2_NUM_PREDICATELOCK_PARTITIONS);
+}
 
 
 /*
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index e9ef0fbfe32..5e8cbdfc70d 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -549,7 +549,7 @@ InitProcess(void)
 	/*
 	 * Arrange to clean up at backend exit.
 	 */
-	on_shmem_exit(ProcKill, 0);
+	on_shmem_exit(ProcKill, DummyDatum);
 
 	/*
 	 * Now that we have a PGPROC, we could try to acquire locks, so initialize
@@ -589,7 +589,7 @@ InitProcessPhase2(void)
 	/*
 	 * Arrange to clean that up at backend exit.
 	 */
-	on_shmem_exit(RemoveProcFromArray, 0);
+	on_shmem_exit(RemoveProcFromArray, DummyDatum);
 }
 
 /*
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index bce37a36d51..007e9cd2417 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -200,7 +200,7 @@ smgrinit(void)
 	RESUME_INTERRUPTS();
 
 	/* register the shutdown proc */
-	on_proc_exit(smgrshutdown, 0);
+	on_proc_exit(smgrshutdown, DummyDatum); // XXX change to void * instead??
 }
 
 /*
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index 62f9ffa0dc0..ba6eca0d489 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -291,7 +291,7 @@ HandleFunctionRequest(StringInfo msgBuf)
 	else
 	{
 		fcinfo->isnull = true;
-		retval = (Datum) 0;
+		retval = DummyDatum;
 	}
 
 	/* ensure we do at least one CHECK_FOR_INTERRUPTS per function call */
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 0cecd464902..96a51cca96b 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -1950,7 +1950,7 @@ exec_bind_message(StringInfo input_message)
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 						 errmsg("unsupported format code: %d",
 								pformat)));
-				pval = 0;		/* keep compiler quiet */
+				pval = DummyDatum;		/* keep compiler quiet */
 			}
 
 			/* Restore message buffer contents */
@@ -4315,7 +4315,7 @@ PostgresMain(const char *dbname, const char *username)
 	 * sure Log_disconnections has its final value.
 	 */
 	if (IsUnderPostmaster && Log_disconnections)
-		on_proc_exit(log_disconnections, 0);
+		on_proc_exit(log_disconnections, DummyDatum);
 
 	pgstat_report_connect(MyDatabaseId);
 
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 4f4191b0ea6..2ed528e28d8 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1172,7 +1172,7 @@ ProcessUtilitySlow(ParseState *pstate,
 							 * parse and validate reloptions for the toast
 							 * table
 							 */
-							toast_options = transformRelOptions((Datum) 0,
+							toast_options = transformRelOptions(DummyDatum,
 																cstmt->options,
 																"toast",
 																validnsps,
diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c
index c5a71331ce8..98bfe79a43a 100644
--- a/src/backend/tsearch/ts_typanalyze.c
+++ b/src/backend/tsearch/ts_typanalyze.c
@@ -285,7 +285,7 @@ compute_tsvector_stats(VacAttrStats *stats,
 		}
 
 		/* If the vector was toasted, free the detoasted copy. */
-		if (TSVectorGetDatum(vector) != value)
+		if (TSVectorGetDatum(vector).value != value.value)
 			pfree(vector);
 	}
 
diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c
index a8ddb610991..03036782ba9 100644
--- a/src/backend/tsearch/wparser.c
+++ b/src/backend/tsearch/wparser.c
@@ -62,7 +62,7 @@ tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo,
 	st->cur = 0;
 	/* lextype takes one dummy argument */
 	st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
-															 (Datum) 0));
+															 DummyDatum));
 	funcctx->user_fctx = st;
 
 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
@@ -99,7 +99,7 @@ tt_process_call(FuncCallContext *funcctx)
 		st->cur++;
 		return result;
 	}
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 Datum
@@ -116,7 +116,8 @@ ts_token_type_byid(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = tt_process_call(funcctx)) != (Datum) 0)
+	result = tt_process_call(funcctx);
+	if (result.value != DummyDatum.value)
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -139,7 +140,8 @@ ts_token_type_byname(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = tt_process_call(funcctx)) != (Datum) 0)
+	result = tt_process_call(funcctx);
+	if (result.value != DummyDatum.value)
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -235,7 +237,7 @@ prs_process_call(FuncCallContext *funcctx)
 		st->cur++;
 		return result;
 	}
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 Datum
@@ -255,7 +257,8 @@ ts_parse_byid(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = prs_process_call(funcctx)) != (Datum) 0)
+	result = prs_process_call(funcctx);
+	if (result.value != DummyDatum.value)
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -279,7 +282,8 @@ ts_parse_byname(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = prs_process_call(funcctx)) != (Datum) 0)
+	result = prs_process_call(funcctx);
+	if (result.value != DummyDatum.value)
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c
index a290cc4c975..22ec4bfc870 100644
--- a/src/backend/utils/activity/backend_status.c
+++ b/src/backend/utils/activity/backend_status.c
@@ -250,7 +250,7 @@ pgstat_beinit(void)
 	MyBEEntry = &BackendStatusArray[MyProcNumber];
 
 	/* Set up a process-exit hook to clean up */
-	on_shmem_exit(pgstat_beshutdown_hook, 0);
+	on_shmem_exit(pgstat_beshutdown_hook, DummyDatum);
 }
 
 
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index ffb5b8cce34..3b2380b51bf 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -657,7 +657,7 @@ pgstat_initialize(void)
 	}
 
 	/* Set up a process-exit hook to clean up */
-	before_shmem_exit(pgstat_shutdown_hook, 0);
+	before_shmem_exit(pgstat_shutdown_hook, DummyDatum);
 
 #ifdef USE_ASSERT_CHECKING
 	pgstat_is_initialized = true;
diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c
index 53e7d534270..921e585216f 100644
--- a/src/backend/utils/activity/pgstat_shmem.c
+++ b/src/backend/utils/activity/pgstat_shmem.c
@@ -805,7 +805,7 @@ pgstat_release_all_entry_refs(bool discard_pending)
 	if (pgStatEntryRefHash == NULL)
 		return;
 
-	pgstat_release_matching_entry_refs(discard_pending, NULL, 0);
+	pgstat_release_matching_entry_refs(discard_pending, NULL, DummyDatum);
 	Assert(pgStatEntryRefHash->members == 0);
 	pgstat_entry_ref_hash_destroy(pgStatEntryRefHash);
 	pgStatEntryRefHash = NULL;
@@ -1051,7 +1051,7 @@ pgstat_drop_matching_entries(bool (*do_drop) (PgStatShared_HashEntry *, Datum),
 void
 pgstat_drop_all_entries(void)
 {
-	pgstat_drop_matching_entries(NULL, 0);
+	pgstat_drop_matching_entries(NULL, DummyDatum);
 }
 
 static void
diff --git a/src/backend/utils/activity/wait_event_funcs.c b/src/backend/utils/activity/wait_event_funcs.c
index ffbb57a8078..9c2489a81c8 100644
--- a/src/backend/utils/activity/wait_event_funcs.c
+++ b/src/backend/utils/activity/wait_event_funcs.c
@@ -114,5 +114,5 @@ pg_get_wait_events(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 1213f9106d5..9dc410fe66c 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -628,7 +628,7 @@ aclitemin(PG_FUNCTION_ARGS)
 	while (isspace((unsigned char) *s))
 		++s;
 	if (*s)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("extra garbage at the end of the ACL specification")));
 
@@ -5053,13 +5053,13 @@ initialize_acl(void)
 		 */
 		CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
 									  RoleMembershipCacheCallback,
-									  (Datum) 0);
+									  DummyDatum);
 		CacheRegisterSyscacheCallback(AUTHOID,
 									  RoleMembershipCacheCallback,
-									  (Datum) 0);
+									  DummyDatum);
 		CacheRegisterSyscacheCallback(DATABASEOID,
 									  RoleMembershipCacheCallback,
-									  (Datum) 0);
+									  DummyDatum);
 	}
 }
 
diff --git a/src/backend/utils/adt/array_selfuncs.c b/src/backend/utils/adt/array_selfuncs.c
index a69a84c2aee..42390d8308f 100644
--- a/src/backend/utils/adt/array_selfuncs.c
+++ b/src/backend/utils/adt/array_selfuncs.c
@@ -411,7 +411,7 @@ calc_arraycontsel(VariableStatData *vardata, Datum constval,
 	}
 
 	/* If constant was toasted, release the copy we made */
-	if (PointerGetDatum(array) != constval)
+	if (PointerGetDatum(array).value != constval.value)
 		pfree(array);
 
 	return selec;
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index 6f61629b977..7e4e3fbbf79 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -426,7 +426,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			count_item->frequency = 1;
 
 		/* Free memory allocated while detoasting. */
-		if (PointerGetDatum(array) != value)
+		if (PointerGetDatum(array).value != value.value)
 			pfree(array);
 		pfree(elem_values);
 		pfree(elem_nulls);
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 8eb342e3382..3cb437849d5 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -150,7 +150,7 @@ array_append(PG_FUNCTION_ARGS)
 	eah = fetch_array_arg_replace_nulls(fcinfo, 0);
 	isNull = PG_ARGISNULL(1);
 	if (isNull)
-		newelem = (Datum) 0;
+		newelem = DummyDatum;
 	else
 		newelem = PG_GETARG_DATUM(1);
 
@@ -232,7 +232,7 @@ array_prepend(PG_FUNCTION_ARGS)
 
 	isNull = PG_ARGISNULL(0);
 	if (isNull)
-		newelem = (Datum) 0;
+		newelem = DummyDatum;
 	else
 		newelem = PG_GETARG_DATUM(0);
 	eah = fetch_array_arg_replace_nulls(fcinfo, 1);
@@ -266,7 +266,7 @@ array_prepend(PG_FUNCTION_ARGS)
 							   -1, my_extra->typlen, my_extra->typbyval, my_extra->typalign);
 
 	/* Readjust result's LB to match the input's, as expected for prepend */
-	Assert(result == EOHPGetRWDatum(&eah->hdr));
+	Assert(result.value == EOHPGetRWDatum(&eah->hdr).value);
 	if (eah->ndims == 1)
 	{
 		/* This is ok whether we've deconstructed or not */
@@ -581,7 +581,7 @@ array_agg_transfn(PG_FUNCTION_ARGS)
 	else
 		state = (ArrayBuildState *) PG_GETARG_POINTER(0);
 
-	elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
+	elem = PG_ARGISNULL(1) ? DummyDatum : PG_GETARG_DATUM(1);
 
 	state = accumArrayResult(state,
 							 elem,
@@ -637,7 +637,7 @@ array_agg_combine(PG_FUNCTION_ARGS)
 											   state1->typbyval,
 											   state1->typlen);
 			else
-				state1->dvalues[i] = (Datum) 0;
+				state1->dvalues[i] = DummyDatum;
 		}
 
 		MemoryContextSwitchTo(old_context);
@@ -676,7 +676,7 @@ array_agg_combine(PG_FUNCTION_ARGS)
 							  state1->typbyval,
 							  state1->typlen);
 			else
-				state1->dvalues[i + state1->nelems] = (Datum) 0;
+				state1->dvalues[i + state1->nelems] = DummyDatum;
 		}
 
 		memcpy(&state1->dnulls[state1->nelems], state2->dnulls,
@@ -862,7 +862,7 @@ array_agg_deserialize(PG_FUNCTION_ARGS)
 
 			if (result->dnulls[i])
 			{
-				result->dvalues[i] = (Datum) 0;
+				result->dvalues[i] = DummyDatum;
 				continue;
 			}
 
@@ -1356,7 +1356,7 @@ array_position_common(FunctionCallInfo fcinfo)
 		/* fast return when the array doesn't have nulls */
 		if (!array_contains_nulls(array))
 			PG_RETURN_NULL();
-		searched_element = (Datum) 0;
+		searched_element = DummyDatum;
 		null_search = true;
 	}
 	else
@@ -1512,7 +1512,7 @@ array_positions(PG_FUNCTION_ARGS)
 		/* fast return when the array doesn't have nulls */
 		if (!array_contains_nulls(array))
 			PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
-		searched_element = (Datum) 0;
+		searched_element = DummyDatum;
 		null_search = true;
 	}
 	else
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index c8f53c6fbe7..2651d1a0e0a 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -253,13 +253,13 @@ array_in(PG_FUNCTION_ARGS)
 	 */
 	p = string;
 	if (!ReadArrayDimensions(&p, &ndim, dim, lBound, string, escontext))
-		return (Datum) 0;
+		return DummyDatum;
 
 	if (ndim == 0)
 	{
 		/* No array dimensions, so next character should be a left brace */
 		if (*p != '{')
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Array value must start with \"{\" or dimension information.")));
@@ -268,7 +268,7 @@ array_in(PG_FUNCTION_ARGS)
 	{
 		/* If array dimensions are given, expect '=' operator */
 		if (strncmp(p, ASSGN, strlen(ASSGN)) != 0)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Missing \"%s\" after array dimensions.",
@@ -279,7 +279,7 @@ array_in(PG_FUNCTION_ARGS)
 			p++;
 
 		if (*p != '{')
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Array contents must start with \"{\".")));
@@ -296,13 +296,13 @@ array_in(PG_FUNCTION_ARGS)
 					  &values, &nulls,
 					  string,
 					  escontext))
-		return (Datum) 0;
+		return DummyDatum;
 
 	/* only whitespace is allowed after the closing brace */
 	while (*p)
 	{
 		if (!scanner_isspace(*p++))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed array literal: \"%s\"", string),
 					 errdetail("Junk after closing right brace.")));
@@ -330,7 +330,7 @@ array_in(PG_FUNCTION_ARGS)
 			nbytes = att_align_nominal(nbytes, typalign);
 			/* check for overflow of total request */
 			if (!AllocSizeIsValid(nbytes))
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 						 errmsg("array size exceeds the maximum allowed (%d)",
 								(int) MaxAllocSize)));
@@ -1880,14 +1880,14 @@ array_get_element(Datum arraydatum,
 	if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	for (i = 0; i < ndim; i++)
 	{
 		if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
 		{
 			*isNull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 	}
 
@@ -1902,7 +1902,7 @@ array_get_element(Datum arraydatum,
 	if (array_get_isnull(arraynullsptr, offset))
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	/*
@@ -1952,14 +1952,14 @@ array_get_element_expanded(Datum arraydatum,
 	if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	for (i = 0; i < ndim; i++)
 	{
 		if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
 		{
 			*isNull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 	}
 
@@ -1983,7 +1983,7 @@ array_get_element_expanded(Datum arraydatum,
 	if (dnulls && dnulls[offset])
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	/*
@@ -2711,7 +2711,7 @@ array_set_element_expanded(Datum arraydatum,
 	{
 		memmove(dvalues + addedbefore, dvalues, eah->nelems * sizeof(Datum));
 		for (i = 0; i < addedbefore; i++)
-			dvalues[i] = (Datum) 0;
+			dvalues[i] = DummyDatum;
 		if (dnulls)
 		{
 			memmove(dnulls + addedbefore, dnulls, eah->nelems * sizeof(bool));
@@ -2725,7 +2725,7 @@ array_set_element_expanded(Datum arraydatum,
 	if (addedafter > 0)
 	{
 		for (i = 0; i < addedafter; i++)
-			dvalues[eah->nelems + i] = (Datum) 0;
+			dvalues[eah->nelems + i] = DummyDatum;
 		if (dnulls)
 		{
 			for (i = 0; i < addedafter; i++)
@@ -3660,7 +3660,7 @@ deconstruct_array(ArrayType *array,
 		/* Get source element, checking for NULL */
 		if (bitmap && (*bitmap & bitmask) == 0)
 		{
-			elems[i] = (Datum) 0;
+			elems[i] = DummyDatum;
 			if (nulls)
 				nulls[i] = true;
 			else
@@ -4687,7 +4687,7 @@ array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
 		if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
 		{
 			*isnull = true;
-			*value = (Datum) 0;
+			*value = DummyDatum;
 		}
 		else
 		{
@@ -4720,7 +4720,7 @@ array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
 								 iterator->current_item++))
 			{
 				nulls[i] = true;
-				values[i] = (Datum) 0;
+				values[i] = DummyDatum;
 			}
 			else
 			{
@@ -6013,7 +6013,7 @@ array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
 	}
 	else
 	{
-		value = 0;
+		value = DummyDatum;
 		isnull = true;
 	}
 
@@ -6052,7 +6052,7 @@ array_fill(PG_FUNCTION_ARGS)
 	}
 	else
 	{
-		value = 0;
+		value = DummyDatum;
 		isnull = true;
 	}
 
@@ -6648,7 +6648,7 @@ array_remove(PG_FUNCTION_ARGS)
 
 	array = array_replace_internal(array,
 								   search, search_isnull,
-								   (Datum) 0, true,
+								   DummyDatum, true,
 								   true, PG_GET_COLLATION(),
 								   fcinfo);
 	PG_RETURN_ARRAYTYPE_P(array);
diff --git a/src/backend/utils/adt/arraysubs.c b/src/backend/utils/adt/arraysubs.c
index 2940fb8e8d7..7d3880205bf 100644
--- a/src/backend/utils/adt/arraysubs.c
+++ b/src/backend/utils/adt/arraysubs.c
@@ -407,7 +407,7 @@ array_subscript_fetch_old(ExprState *state,
 	if (*op->resnull)
 	{
 		/* whole array is null, so any element is too */
-		sbsrefstate->prevvalue = (Datum) 0;
+		sbsrefstate->prevvalue = DummyDatum;
 		sbsrefstate->prevnull = true;
 	}
 	else
@@ -447,7 +447,7 @@ array_subscript_fetch_old_slice(ExprState *state,
 	if (*op->resnull)
 	{
 		/* whole array is null, so any slice is too */
-		sbsrefstate->prevvalue = (Datum) 0;
+		sbsrefstate->prevvalue = DummyDatum;
 		sbsrefstate->prevnull = true;
 	}
 	else
diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index 474653797b5..5910ccfa3e5 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -145,7 +145,7 @@ boolin(PG_FUNCTION_ARGS)
 	if (parse_bool_with_len(str, len, &result))
 		PG_RETURN_BOOL(result);
 
-	ereturn(fcinfo->context, (Datum) 0,
+	ereturn(fcinfo->context, DummyDatum,
 			(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 			 errmsg("invalid input syntax for type %s: \"%s\"",
 					"boolean", in_str)));
diff --git a/src/backend/utils/adt/bytea.c b/src/backend/utils/adt/bytea.c
index 6e7b914c563..631f39a8183 100644
--- a/src/backend/utils/adt/bytea.c
+++ b/src/backend/utils/adt/bytea.c
@@ -239,7 +239,7 @@ byteain(PG_FUNCTION_ARGS)
 			/*
 			 * one backslash, not followed by another or ### valid octal
 			 */
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s", "bytea")));
 		}
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index 611d23f3cb0..6175ab77be9 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -287,7 +287,7 @@ cash_in(PG_FUNCTION_ARGS)
 
 			if (pg_mul_s64_overflow(value, 10, &value) ||
 				pg_sub_s64_overflow(value, digit, &value))
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 						 errmsg("value \"%s\" is out of range for type %s",
 								str, "money")));
@@ -312,7 +312,7 @@ cash_in(PG_FUNCTION_ARGS)
 	{
 		/* remember we build the value in the negative */
 		if (pg_sub_s64_overflow(value, 1, &value))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("value \"%s\" is out of range for type %s",
 							str, "money")));
@@ -322,7 +322,7 @@ cash_in(PG_FUNCTION_ARGS)
 	for (; dec < fpoint; dec++)
 	{
 		if (pg_mul_s64_overflow(value, 10, &value))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("value \"%s\" is out of range for type %s",
 							str, "money")));
@@ -349,7 +349,7 @@ cash_in(PG_FUNCTION_ARGS)
 		else if (strncmp(s, csymbol, strlen(csymbol)) == 0)
 			s += strlen(csymbol);
 		else
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"money", str)));
@@ -362,7 +362,7 @@ cash_in(PG_FUNCTION_ARGS)
 	if (sgn > 0)
 	{
 		if (value == PG_INT64_MIN)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("value \"%s\" is out of range for type %s",
 							str, "money")));
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 344f58b92f7..e91932cc168 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -163,7 +163,7 @@ date_in(PG_FUNCTION_ARGS)
 
 	/* Prevent overflow in Julian-day routines */
 	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("date out of range: \"%s\"", str)));
 
@@ -171,7 +171,7 @@ date_in(PG_FUNCTION_ARGS)
 
 	/* Now check for just-out-of-range dates */
 	if (!IS_VALID_DATE(date))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("date out of range: \"%s\"", str)));
 
@@ -472,7 +472,7 @@ date_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -488,7 +488,7 @@ date_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 680fee2a844..f92f7a49d0d 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -5388,5 +5388,5 @@ pg_timezone_names(PG_FUNCTION_ARGS)
 	}
 
 	pg_tzenumerate_end(tzenum);
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c
index 614644a4e2a..37685a8113a 100644
--- a/src/backend/utils/adt/datum.c
+++ b/src/backend/utils/adt/datum.c
@@ -232,7 +232,7 @@ datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
 		 * inside the "Datum".  We assume instead that any given datatype is
 		 * consistent about how it fills extraneous bits in the Datum.
 		 */
-		res = (value1 == value2);
+		res = (value1.value == value2.value);
 	}
 	else
 	{
@@ -271,7 +271,7 @@ datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
 
 	if (typByVal)
 	{
-		result = (value1 == value2);
+		result = (value1.value == value2.value);
 	}
 	else if (typLen > 0)
 	{
@@ -531,7 +531,7 @@ datumRestore(char **start_address, bool *isnull)
 	if (header == -2)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	/* OK, datum is not null. */
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index fcc6981632b..f0e563033d2 100644
--- a/src/backend/utils/adt/enum.c
+++ b/src/backend/utils/adt/enum.c
@@ -116,7 +116,7 @@ enum_in(PG_FUNCTION_ARGS)
 
 	/* must check length to prevent Assert failure within SearchSysCache */
 	if (strlen(name) >= NAMEDATALEN)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input value for enum %s: \"%s\"",
 						format_type_be(enumtypoid),
@@ -126,7 +126,7 @@ enum_in(PG_FUNCTION_ARGS)
 						  ObjectIdGetDatum(enumtypoid),
 						  CStringGetDatum(name));
 	if (!HeapTupleIsValid(tup))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input value for enum %s: \"%s\"",
 						format_type_be(enumtypoid),
diff --git a/src/backend/utils/adt/expandedrecord.c b/src/backend/utils/adt/expandedrecord.c
index 13752db44e8..69c8b75cede 100644
--- a/src/backend/utils/adt/expandedrecord.c
+++ b/src/backend/utils/adt/expandedrecord.c
@@ -1069,7 +1069,7 @@ expanded_record_fetch_field(ExpandedRecordHeader *erh, int fnumber,
 		if (ExpandedRecordIsEmpty(erh))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 		/* Make sure we have deconstructed form */
 		deconstruct_expanded_record(erh);
@@ -1077,7 +1077,7 @@ expanded_record_fetch_field(ExpandedRecordHeader *erh, int fnumber,
 		if (unlikely(fnumber > erh->nfields))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 		*isnull = erh->dnulls[fnumber - 1];
 		return erh->dvalues[fnumber - 1];
@@ -1088,7 +1088,7 @@ expanded_record_fetch_field(ExpandedRecordHeader *erh, int fnumber,
 		if (erh->fvalue == NULL)
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 		/* heap_getsysattr doesn't actually use tupdesc, so just pass null */
 		return heap_getsysattr(erh->fvalue, fnumber, NULL, isnull);
@@ -1584,7 +1584,7 @@ check_domain_for_new_tuple(ExpandedRecordHeader *erh, HeapTuple tuple)
 		/* We run domain_check in a short-lived context to limit cruft */
 		oldcxt = MemoryContextSwitchTo(get_short_term_cxt(erh));
 
-		domain_check((Datum) 0, true,
+		domain_check(DummyDatum, true,
 					 erh->er_decltypeid,
 					 &erh->er_domaininfo,
 					 erh->hdr.eoh_context);
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 1d05481181d..9e6b9ff303b 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -4212,7 +4212,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 
 	if (!do_to_timestamp(date_txt, fmt, collid, strict,
 						 &tm, &fsec, &ftz, &fprec, &flags, escontext))
-		return (Datum) 0;
+		return DummyDatum;
 
 	*typmod = fprec ? fprec : -1;	/* fractional part precision */
 
@@ -4237,13 +4237,13 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 					 */
 					Assert(!strict);
 
-					ereturn(escontext, (Datum) 0,
+					ereturn(escontext, DummyDatum,
 							(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
 							 errmsg("missing time zone in input string for type timestamptz")));
 				}
 
 				if (tm2timestamp(&tm, fsec, tz, &result) != 0)
-					ereturn(escontext, (Datum) 0,
+					ereturn(escontext, DummyDatum,
 							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 							 errmsg("timestamptz out of range")));
 
@@ -4257,7 +4257,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 				Timestamp	result;
 
 				if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
-					ereturn(escontext, (Datum) 0,
+					ereturn(escontext, DummyDatum,
 							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 							 errmsg("timestamp out of range")));
 
@@ -4271,7 +4271,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 		{
 			if (flags & DCH_ZONED)
 			{
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
 						 errmsg("datetime format is zoned but not timed")));
 			}
@@ -4281,7 +4281,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 
 				/* Prevent overflow in Julian-day routines */
 				if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
-					ereturn(escontext, (Datum) 0,
+					ereturn(escontext, DummyDatum,
 							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 							 errmsg("date out of range: \"%s\"",
 									text_to_cstring(date_txt))));
@@ -4291,7 +4291,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 
 				/* Now check for just-out-of-range dates */
 				if (!IS_VALID_DATE(result))
-					ereturn(escontext, (Datum) 0,
+					ereturn(escontext, DummyDatum,
 							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 							 errmsg("date out of range: \"%s\"",
 									text_to_cstring(date_txt))));
@@ -4320,13 +4320,13 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 				 */
 				Assert(!strict);
 
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
 						 errmsg("missing time zone in input string for type timetz")));
 			}
 
 			if (tm2timetz(&tm, fsec, *tz, result) != 0)
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("timetz out of range")));
 
@@ -4340,7 +4340,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 			TimeADT		result;
 
 			if (tm2time(&tm, fsec, &result) != 0)
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("time out of range")));
 
@@ -4352,7 +4352,7 @@ parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 	}
 	else
 	{
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
 				 errmsg("datetime format is not dated and not timed")));
 	}
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index 80bb807fbe9..6d24bf69ff6 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -522,7 +522,7 @@ pg_ls_dir(PG_FUNCTION_ARGS)
 	{
 		/* Return empty tuplestore if appropriate */
 		if (missing_ok && errno == ENOENT)
-			return (Datum) 0;
+			return DummyDatum;
 		/* Otherwise, we can let ReadDir() throw the error */
 	}
 
@@ -544,7 +544,7 @@ pg_ls_dir(PG_FUNCTION_ARGS)
 	}
 
 	FreeDir(dirdesc);
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -585,7 +585,7 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
 	{
 		/* Return empty tuplestore if appropriate */
 		if (missing_ok && errno == ENOENT)
-			return (Datum) 0;
+			return DummyDatum;
 		/* Otherwise, we can let ReadDir() throw the error */
 	}
 
@@ -625,7 +625,7 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
 	}
 
 	FreeDir(dirdesc);
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /* Function to return the list of files in the log directory */
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 377a1b3f3ad..38d8caf8478 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -993,7 +993,7 @@ line_in(PG_FUNCTION_ARGS)
 		if (!line_decode(s + 1, str, line, escontext))
 			PG_RETURN_NULL();
 		if (FPzero(line->A) && FPzero(line->B))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid line specification: A and B cannot both be zero")));
 	}
@@ -1003,7 +1003,7 @@ line_in(PG_FUNCTION_ARGS)
 						 escontext))
 			PG_RETURN_NULL();
 		if (point_eq_point(&lseg.p[0], &lseg.p[1]))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid line specification: must be two distinct points")));
 
@@ -1412,7 +1412,7 @@ path_in(PG_FUNCTION_ARGS)
 	int			depth = 0;
 
 	if ((npts = pair_count(str, ',')) <= 0)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"path", str)));
@@ -1433,7 +1433,7 @@ path_in(PG_FUNCTION_ARGS)
 
 	/* Check for integer overflow */
 	if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("too many points requested")));
 
@@ -1449,7 +1449,7 @@ path_in(PG_FUNCTION_ARGS)
 	if (depth >= 1)
 	{
 		if (*s++ != RDELIM)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"path", str)));
@@ -1457,7 +1457,7 @@ path_in(PG_FUNCTION_ARGS)
 			s++;
 	}
 	if (*s != '\0')
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"path", str)));
@@ -3423,7 +3423,7 @@ poly_in(PG_FUNCTION_ARGS)
 	bool		isopen;
 
 	if ((npts = pair_count(str, ',')) <= 0)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"polygon", str)));
@@ -3433,7 +3433,7 @@ poly_in(PG_FUNCTION_ARGS)
 
 	/* Check for integer overflow */
 	if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("too many points requested")));
 
@@ -4645,7 +4645,7 @@ circle_in(PG_FUNCTION_ARGS)
 
 	/* We have to accept NaN. */
 	if (circle->radius < 0.0)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"circle", str)));
@@ -4660,14 +4660,14 @@ circle_in(PG_FUNCTION_ARGS)
 				s++;
 		}
 		else
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"circle", str)));
 	}
 
 	if (*s != '\0')
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"circle", str)));
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index b5781989a64..313402cb14b 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -169,19 +169,19 @@ int2vectorin(PG_FUNCTION_ARGS)
 		l = strtol(intString, &endp, 10);
 
 		if (intString == endp)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"smallint", intString)));
 
 		if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("value \"%s\" is out of range for type %s", intString,
 							"smallint")));
 
 		if (*endp && *endp != ' ')
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"smallint", intString)));
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index e9d370cb3da..a241d459249 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -827,7 +827,7 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
 	/* fast path for NULLs */
 	if (PG_ARGISNULL(1))
 	{
-		datum_to_json_internal((Datum) 0, true, state->str, JSONTYPE_NULL,
+		datum_to_json_internal(DummyDatum, true, state->str, JSONTYPE_NULL,
 							   InvalidOid, false);
 		PG_RETURN_POINTER(state);
 	}
@@ -1132,7 +1132,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
 	appendStringInfoString(state->str, " : ");
 
 	if (PG_ARGISNULL(2))
-		arg = (Datum) 0;
+		arg = DummyDatum;
 	else
 		arg = PG_GETARG_DATUM(2);
 
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index da94d424d61..fde816d2d7f 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -267,7 +267,7 @@ jsonb_from_cstring(char *json, int len, bool unique_keys, Node *escontext)
 	sem.object_field_start = jsonb_in_object_field_start;
 
 	if (!pg_parse_json_or_errsave(&lex, &sem, escontext))
-		return (Datum) 0;
+		return DummyDatum;
 
 	/* after parsing, the item member has the composed jsonb structure */
 	PG_RETURN_POINTER(JsonbValueToJsonb(state.res));
@@ -1551,7 +1551,7 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
 
 	/* turn the argument into jsonb in the normal function context */
 
-	val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
+	val = PG_ARGISNULL(1) ? DummyDatum : PG_GETARG_DATUM(1);
 
 	memset(&elem, 0, sizeof(JsonbInState));
 
@@ -1761,7 +1761,7 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
 
 	jbkey = JsonbValueToJsonb(elem.res);
 
-	val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
+	val = PG_ARGISNULL(2) ? DummyDatum : PG_GETARG_DATUM(2);
 
 	memset(&elem, 0, sizeof(JsonbInState));
 
diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c
index 9b56248cf0b..316cdcce4b0 100644
--- a/src/backend/utils/adt/jsonb_gin.c
+++ b/src/backend/utils/adt/jsonb_gin.c
@@ -1401,7 +1401,7 @@ make_scalar_key(const JsonbValue *scalarVal, bool is_key)
 			break;
 		default:
 			elog(ERROR, "unrecognized jsonb scalar type: %d", scalarVal->type);
-			item = 0;			/* keep compiler quiet */
+			item = DummyDatum;			/* keep compiler quiet */
 			break;
 	}
 
diff --git a/src/backend/utils/adt/jsonbsubs.c b/src/backend/utils/adt/jsonbsubs.c
index de64d498512..e936a447888 100644
--- a/src/backend/utils/adt/jsonbsubs.c
+++ b/src/backend/utils/adt/jsonbsubs.c
@@ -329,7 +329,7 @@ jsonb_subscript_fetch_old(ExprState *state,
 	if (*op->resnull)
 	{
 		/* whole jsonb is null, so any element is too */
-		sbsrefstate->prevvalue = (Datum) 0;
+		sbsrefstate->prevvalue = DummyDatum;
 		sbsrefstate->prevnull = true;
 	}
 	else
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index 370456408bf..a1453956b54 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -2027,7 +2027,7 @@ each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 				{
 					/* a json null is an sql null in text mode */
 					nulls[1] = true;
-					values[1] = (Datum) NULL;
+					values[1] = DummyDatum;
 				}
 				else
 					values[1] = PointerGetDatum(JsonbValueAsText(&v));
@@ -2139,7 +2139,7 @@ each_object_field_end(void *state, char *fname, bool isnull)
 	if (isnull && _state->normalize_results)
 	{
 		nulls[1] = true;
-		values[1] = (Datum) 0;
+		values[1] = DummyDatum;
 	}
 	else if (_state->next_scalar)
 	{
@@ -2266,7 +2266,7 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
 				{
 					/* a json null is an sql null in text mode */
 					nulls[0] = true;
-					values[0] = (Datum) NULL;
+					values[0] = DummyDatum;
 				}
 				else
 					values[0] = PointerGetDatum(JsonbValueAsText(&v));
@@ -2389,7 +2389,7 @@ elements_array_element_end(void *state, bool isnull)
 	if (isnull && _state->normalize_results)
 	{
 		nulls[0] = true;
-		values[0] = (Datum) NULL;
+		values[0] = DummyDatum;
 	}
 	else if (_state->next_scalar)
 	{
@@ -2942,7 +2942,7 @@ populate_array(ArrayIOData *aio,
 								 : strlen(jsv->val.json.str)))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 	}
 	else
@@ -2951,7 +2951,7 @@ populate_array(ArrayIOData *aio,
 		if (!populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 		ctx.dims[0] = ctx.sizes[0];
 	}
@@ -3070,7 +3070,7 @@ populate_composite(CompositeIOData *io,
 	update_cached_tupdesc(io, mcxt);
 
 	if (*isnull)
-		result = (Datum) 0;
+		result = DummyDatum;
 	else
 	{
 		HeapTupleHeader tuple;
@@ -3080,7 +3080,7 @@ populate_composite(CompositeIOData *io,
 		if (!JsValueToJsObject(jsv, &jso, escontext))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 
 		/* populate resulting record tuple */
@@ -3090,7 +3090,7 @@ populate_composite(CompositeIOData *io,
 		if (SOFT_ERROR_OCCURRED(escontext))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 		result = HeapTupleHeaderGetDatum(tuple);
 
@@ -3108,7 +3108,7 @@ populate_composite(CompositeIOData *io,
 							   escontext))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 	}
 
@@ -3202,7 +3202,7 @@ populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv,
 	if (!InputFunctionCallSafe(&io->typiofunc, str, io->typioparam, typmod,
 							   escontext, &res))
 	{
-		res = (Datum) 0;
+		res = DummyDatum;
 		*isnull = true;
 	}
 
@@ -3226,7 +3226,7 @@ populate_domain(DomainIOData *io,
 	Datum		res;
 
 	if (*isnull)
-		res = (Datum) 0;
+		res = DummyDatum;
 	else
 	{
 		res = populate_record_field(io->base_io,
@@ -3240,7 +3240,7 @@ populate_domain(DomainIOData *io,
 						   escontext))
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	return res;
@@ -3440,7 +3440,7 @@ populate_record_field(ColumnIOData *col,
 	if (*isnull &&
 		typcat != TYPECAT_DOMAIN &&
 		typcat != TYPECAT_COMPOSITE_DOMAIN)
-		return (Datum) 0;
+		return DummyDatum;
 
 	switch (typcat)
 	{
@@ -3468,7 +3468,7 @@ populate_record_field(ColumnIOData *col,
 
 		default:
 			elog(ERROR, "unrecognized type category '%c'", typcat);
-			return (Datum) 0;
+			return DummyDatum;
 	}
 }
 
@@ -3575,7 +3575,7 @@ populate_record(TupleDesc tupdesc,
 	{
 		for (i = 0; i < ncolumns; ++i)
 		{
-			values[i] = (Datum) 0;
+			values[i] = DummyDatum;
 			nulls[i] = true;
 		}
 	}
@@ -3612,7 +3612,7 @@ populate_record(TupleDesc tupdesc,
 										  att->atttypmod,
 										  colname,
 										  mcxt,
-										  nulls[i] ? (Datum) 0 : values[i],
+										  nulls[i] ? DummyDatum : values[i],
 										  &field,
 										  &nulls[i],
 										  escontext,
@@ -4946,7 +4946,7 @@ jsonb_set_lax(PG_FUNCTION_ARGS)
 				 errmsg("JSON value must not be null"),
 				 errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
 				 errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
-		return (Datum) 0;		/* silence stupider compilers */
+		return DummyDatum;		/* silence stupider compilers */
 	}
 	else if (strcmp(handle_val, "use_json_null") == 0)
 	{
@@ -4973,7 +4973,7 @@ jsonb_set_lax(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
-		return (Datum) 0;		/* silence stupider compilers */
+		return DummyDatum;		/* silence stupider compilers */
 	}
 }
 
diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c
index 762f7e8a09d..7c58223eaf7 100644
--- a/src/backend/utils/adt/jsonpath.c
+++ b/src/backend/utils/adt/jsonpath.c
@@ -177,10 +177,10 @@ jsonPathFromCstring(char *in, int len, struct Node *escontext)
 	StringInfoData buf;
 
 	if (SOFT_ERROR_OCCURRED(escontext))
-		return (Datum) 0;
+		return DummyDatum;
 
 	if (!jsonpath)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"", "jsonpath",
 						in)));
@@ -192,7 +192,7 @@ jsonPathFromCstring(char *in, int len, struct Node *escontext)
 
 	if (!flattenJsonPathParseItem(&buf, NULL, escontext,
 								  jsonpath->expr, 0, false))
-		return (Datum) 0;
+		return DummyDatum;
 
 	res = (JsonPath *) buf.data;
 	SET_VARSIZE(res, buf.len);
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 5a562535223..577fbbca12c 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -3925,7 +3925,7 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty,
 	{
 		*error = true;
 		*empty = false;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	/*
@@ -3971,7 +3971,7 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty,
 		if (error)
 		{
 			*error = true;
-			return (Datum) 0;
+			return DummyDatum;
 		}
 
 		if (column_name)
@@ -4464,7 +4464,7 @@ JsonTableGetValue(TableFuncScanState *state, int colnum,
 	/* Row pattern value is NULL */
 	if (current->isnull)
 	{
-		result = (Datum) 0;
+		result = DummyDatum;
 		*isnull = true;
 	}
 	/* Evaluate JsonExpr. */
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index 3644e9735f5..f7efba1f61e 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -89,7 +89,7 @@ macaddr_in(PG_FUNCTION_ARGS)
 		count = sscanf(str, "%2x%2x%2x%2x%2x%2x%1s",
 					   &a, &b, &c, &d, &e, &f, junk);
 	if (count != 6)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"", "macaddr",
 						str)));
@@ -97,7 +97,7 @@ macaddr_in(PG_FUNCTION_ARGS)
 	if ((a < 0) || (a > 255) || (b < 0) || (b > 255) ||
 		(c < 0) || (c > 255) || (d < 0) || (d > 255) ||
 		(e < 0) || (e > 255) || (f < 0) || (f > 255))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("invalid octet value in \"macaddr\" value: \"%s\"", str)));
 
@@ -504,9 +504,9 @@ macaddr_abbrev_convert(Datum original, SortSupport ssup)
 		uint32		tmp;
 
 #if SIZEOF_DATUM == 8
-		tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
+		tmp = (uint32) res.value ^ (uint32) ((uint64) res.value >> 32);
 #else							/* SIZEOF_DATUM != 8 */
-		tmp = (uint32) res;
+		tmp = (uint32) res.value;
 #endif
 
 		addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
@@ -520,7 +520,7 @@ macaddr_abbrev_convert(Datum original, SortSupport ssup)
 	 * comparator would have to call memcmp() with a pair of pointers to the
 	 * first byte of each abbreviated key, which is slower.
 	 */
-	res = DatumBigEndianToNative(res);
+	res.value = DatumBigEndianToNative(res);
 
 	return res;
 }
diff --git a/src/backend/utils/adt/mac8.c b/src/backend/utils/adt/mac8.c
index 08e41ba4eea..8106d5f11d4 100644
--- a/src/backend/utils/adt/mac8.c
+++ b/src/backend/utils/adt/mac8.c
@@ -221,7 +221,7 @@ macaddr8_in(PG_FUNCTION_ARGS)
 	PG_RETURN_MACADDR8_P(result);
 
 fail:
-	ereturn(escontext, (Datum) 0,
+	ereturn(escontext, DummyDatum,
 			(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 			 errmsg("invalid input syntax for type %s: \"%s\"", "macaddr8",
 					str)));
diff --git a/src/backend/utils/adt/mcxtfuncs.c b/src/backend/utils/adt/mcxtfuncs.c
index fe6dce9cba3..df7cfd3a780 100644
--- a/src/backend/utils/adt/mcxtfuncs.c
+++ b/src/backend/utils/adt/mcxtfuncs.c
@@ -244,7 +244,7 @@ pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
 
 	hash_destroy(context_id_lookup);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 6fcfd031428..61efdeb83ee 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -236,7 +236,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
 		ereport(WARNING,
 				(errmsg("global tablespace never has databases")));
 		/* return empty tuplestore */
-		return (Datum) 0;
+		PG_RETURN_DUMMY();
 	}
 
 	if (tablespaceOid == DEFAULTTABLESPACE_OID)
@@ -258,7 +258,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
 		ereport(WARNING,
 				(errmsg("%u is not a tablespace OID", tablespaceOid)));
 		/* return empty tuplestore */
-		return (Datum) 0;
+		PG_RETURN_DUMMY();
 	}
 
 	while ((de = ReadDir(dirdesc, location)) != NULL)
@@ -290,7 +290,7 @@ pg_tablespace_databases(PG_FUNCTION_ARGS)
 	}
 
 	FreeDir(dirdesc);
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
 
 
diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c
index 097f91d2346..ef12058f542 100644
--- a/src/backend/utils/adt/multirangetypes.c
+++ b/src/backend/utils/adt/multirangetypes.c
@@ -145,7 +145,7 @@ multirange_in(PG_FUNCTION_ARGS)
 	if (*ptr == '{')
 		ptr++;
 	else
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed multirange literal: \"%s\"",
 						input_str),
@@ -158,7 +158,7 @@ multirange_in(PG_FUNCTION_ARGS)
 		char		ch = *ptr;
 
 		if (ch == '\0')
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("malformed multirange literal: \"%s\"",
 							input_str),
@@ -187,7 +187,7 @@ multirange_in(PG_FUNCTION_ARGS)
 					parse_state = MULTIRANGE_AFTER_RANGE;
 				}
 				else
-					ereturn(escontext, (Datum) 0,
+					ereturn(escontext, DummyDatum,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed multirange literal: \"%s\"",
 									input_str),
@@ -261,7 +261,7 @@ multirange_in(PG_FUNCTION_ARGS)
 				else if (ch == '}')
 					parse_state = MULTIRANGE_FINISHED;
 				else
-					ereturn(escontext, (Datum) 0,
+					ereturn(escontext, DummyDatum,
 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 							 errmsg("malformed multirange literal: \"%s\"",
 									input_str),
@@ -285,7 +285,7 @@ multirange_in(PG_FUNCTION_ARGS)
 		ptr++;
 
 	if (*ptr != '\0')
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("malformed multirange literal: \"%s\"",
 						input_str),
@@ -772,7 +772,7 @@ multirange_get_bounds(TypeCacheEntry *rangetyp,
 		ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
 	}
 	else
-		lbound = (Datum) 0;
+		lbound = DummyDatum;
 
 	/* fetch upper bound, if any */
 	if (RANGE_HAS_UBOUND(flags))
@@ -782,7 +782,7 @@ multirange_get_bounds(TypeCacheEntry *rangetyp,
 		/* no need for att_addlength_pointer */
 	}
 	else
-		ubound = (Datum) 0;
+		ubound = DummyDatum;
 
 	/* emit results */
 	lower->val = lbound;
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 9fd211b2d45..837f5a6603d 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -643,23 +643,23 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 
 		/* Must byteswap on little-endian machines */
 #ifndef WORDS_BIGENDIAN
-		ipaddr_datum = pg_bswap32(ipaddr_datum32);
+		ipaddr_datum.value = pg_bswap32(ipaddr_datum32);
 #else
-		ipaddr_datum = ipaddr_datum32;
+		ipaddr_datum.value = ipaddr_datum32;
 #endif
 
 		/* Initialize result without setting ipfamily bit */
-		res = (Datum) 0;
+		res = DummyDatum;
 	}
 	else
 	{
 		memcpy(&ipaddr_datum, ip_addr(authoritative), sizeof(Datum));
 
 		/* Must byteswap on little-endian machines */
-		ipaddr_datum = DatumBigEndianToNative(ipaddr_datum);
+		ipaddr_datum.value = DatumBigEndianToNative(ipaddr_datum);
 
 		/* Initialize result with ipfamily (most significant) bit set */
-		res = ((Datum) 1) << (SIZEOF_DATUM * BITS_PER_BYTE - 1);
+		res.value = ((uintptr_t) 1) << (SIZEOF_DATUM * BITS_PER_BYTE - 1);
 	}
 
 	/*
@@ -685,19 +685,19 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 	if (ip_bits(authoritative) == 0)
 	{
 		/* Fit as many ipaddr bits as possible into subnet */
-		subnet_bitmask = ((Datum) 0) - 1;
-		network = 0;
+		subnet_bitmask.value = (DummyDatum.value) - 1;
+		network = DummyDatum;
 	}
 	else if (ip_bits(authoritative) < SIZEOF_DATUM * BITS_PER_BYTE)
 	{
 		/* Split ipaddr bits between network and subnet */
-		subnet_bitmask = (((Datum) 1) << subnet_size) - 1;
-		network = ipaddr_datum & ~subnet_bitmask;
+		subnet_bitmask.value = (1 << subnet_size) - 1;
+		network.value = ipaddr_datum.value & ~subnet_bitmask.value;
 	}
 	else
 	{
 		/* Fit as many ipaddr bits as possible into network */
-		subnet_bitmask = 0;
+		subnet_bitmask.value = 0;
 		network = ipaddr_datum;
 	}
 
@@ -708,7 +708,7 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 		 * IPv4 with 8 byte datums: keep all 32 netmasked bits, netmask size,
 		 * and most significant 25 subnet bits
 		 */
-		Datum		netmask_size = (Datum) ip_bits(authoritative);
+		Datum		netmask_size = CharGetDatum(ip_bits(authoritative));
 		Datum		subnet;
 
 		/*
@@ -721,14 +721,14 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 		 * ip_bits(), even though the comparison won't reach the netmask_size
 		 * bits.
 		 */
-		network <<= (ABBREV_BITS_INET4_NETMASK_SIZE +
+		network.value <<= (ABBREV_BITS_INET4_NETMASK_SIZE +
 					 ABBREV_BITS_INET4_SUBNET);
 
 		/* Shift size to make room for subnet bits at the end */
-		netmask_size <<= ABBREV_BITS_INET4_SUBNET;
+		netmask_size.value <<= ABBREV_BITS_INET4_SUBNET;
 
 		/* Extract subnet bits without shifting them */
-		subnet = ipaddr_datum & subnet_bitmask;
+		subnet.value = ipaddr_datum.value & subnet_bitmask.value;
 
 		/*
 		 * If we have more than 25 subnet bits, we can't fit everything. Shift
@@ -741,13 +741,13 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 		 * get that far.
 		 */
 		if (subnet_size > ABBREV_BITS_INET4_SUBNET)
-			subnet >>= subnet_size - ABBREV_BITS_INET4_SUBNET;
+			subnet.value >>= subnet_size - ABBREV_BITS_INET4_SUBNET;
 
 		/*
 		 * Assemble the final abbreviated key without clobbering the ipfamily
 		 * bit that must remain a zero.
 		 */
-		res |= network | netmask_size | subnet;
+		res.value |= network.value | netmask_size.value | subnet.value;
 	}
 	else
 #endif
@@ -757,7 +757,7 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 		 * netmasked bits as will fit in final abbreviated key. Avoid
 		 * clobbering the ipfamily bit that was set earlier.
 		 */
-		res |= network >> 1;
+		res.value |= network.value >> 1;
 	}
 
 	uss->input_count += 1;
@@ -768,9 +768,9 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 		uint32		tmp;
 
 #if SIZEOF_DATUM == 8
-		tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
+		tmp = (uint32) res.value ^ (uint32) ((uint64) res.value >> 32);
 #else							/* SIZEOF_DATUM != 8 */
-		tmp = (uint32) res;
+		tmp = (uint32) res.value;
 #endif
 
 		addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
diff --git a/src/backend/utils/adt/network_gist.c b/src/backend/utils/adt/network_gist.c
index a08c4953789..2f1e6feb79e 100644
--- a/src/backend/utils/adt/network_gist.c
+++ b/src/backend/utils/adt/network_gist.c
@@ -566,7 +566,7 @@ inet_gist_compress(PG_FUNCTION_ARGS)
 		}
 		else
 		{
-			gistentryinit(*retval, (Datum) 0,
+			gistentryinit(*retval, DummyDatum,
 						  entry->rel, entry->page,
 						  entry->offset, false);
 		}
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index c9233565d57..e2c50eccfc5 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -403,8 +403,8 @@ typedef struct NumericSumAccum
  */
 #define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
 #if SIZEOF_DATUM == 8
-#define NumericAbbrevGetDatum(X) ((Datum) (X))
-#define DatumGetNumericAbbrev(X) ((int64) (X))
+#define NumericAbbrevGetDatum(X) ((Datum){.value=X})
+#define DatumGetNumericAbbrev(X) ((int64) (X.value))
 #define NUMERIC_ABBREV_NAN		 NumericAbbrevGetDatum(PG_INT64_MIN)
 #define NUMERIC_ABBREV_PINF		 NumericAbbrevGetDatum(-PG_INT64_MAX)
 #define NUMERIC_ABBREV_NINF		 NumericAbbrevGetDatum(PG_INT64_MAX)
@@ -790,7 +790,7 @@ numeric_in(PG_FUNCTION_ARGS)
 		res = make_result_opt_error(&value, &have_error);
 
 		if (have_error)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("value overflows numeric format")));
 
@@ -800,7 +800,7 @@ numeric_in(PG_FUNCTION_ARGS)
 	PG_RETURN_NUMERIC(res);
 
 invalid_syntax:
-	ereturn(escontext, (Datum) 0,
+	ereturn(escontext, DummyDatum,
 			(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 			 errmsg("invalid input syntax for type %s: \"%s\"",
 					"numeric", str)));
@@ -1528,7 +1528,7 @@ numeric_sign(PG_FUNCTION_ARGS)
 	}
 
 	Assert(false);
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 
@@ -2880,7 +2880,7 @@ hash_numeric(PG_FUNCTION_ARGS)
 						  hash_len * sizeof(NumericDigit));
 
 	/* Mix in the weight, via XOR */
-	result = digit_hash ^ weight;
+	result.value = digit_hash.value ^ weight;
 
 	PG_RETURN_DATUM(result);
 }
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 9457d239715..4de4699f5eb 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -739,7 +739,7 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)
 	Datum	   *result_datum;
 	bool	   *result_isnull;
 	int64		rownum = 0;
-	Datum		val = (Datum) 0;
+	Datum		val = DummyDatum;
 	bool		isnull = true;
 	int			i;
 
@@ -788,7 +788,7 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)
 		if (pct_info[i].first_row > 0)
 			break;
 
-		result_datum[idx] = (Datum) 0;
+		result_datum[idx] = DummyDatum;
 		result_isnull[idx] = true;
 	}
 
@@ -859,8 +859,8 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo,
 	Datum	   *result_datum;
 	bool	   *result_isnull;
 	int64		rownum = 0;
-	Datum		first_val = (Datum) 0;
-	Datum		second_val = (Datum) 0;
+	Datum		first_val = DummyDatum;
+	Datum		second_val = DummyDatum;
 	bool		isnull;
 	int			i;
 
@@ -911,7 +911,7 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo,
 		if (pct_info[i].first_row > 0)
 			break;
 
-		result_datum[idx] = (Datum) 0;
+		result_datum[idx] = DummyDatum;
 		result_isnull[idx] = true;
 	}
 
@@ -1035,14 +1035,14 @@ mode_final(PG_FUNCTION_ARGS)
 	OSAPerGroupState *osastate;
 	Datum		val;
 	bool		isnull;
-	Datum		mode_val = (Datum) 0;
+	Datum		mode_val = DummyDatum;
 	int64		mode_freq = 0;
-	Datum		last_val = (Datum) 0;
+	Datum		last_val = DummyDatum;
 	int64		last_val_freq = 0;
 	bool		last_val_is_mode = false;
 	FmgrInfo   *equalfn;
-	Datum		abbrev_val = (Datum) 0;
-	Datum		last_abbrev_val = (Datum) 0;
+	Datum		abbrev_val = DummyDatum;
+	Datum		last_abbrev_val = DummyDatum;
 	bool		shouldfree;
 
 	Assert(AggCheckCallContext(fcinfo, NULL) == AGG_CONTEXT_AGGREGATE);
@@ -1090,7 +1090,7 @@ mode_final(PG_FUNCTION_ARGS)
 			last_val_is_mode = true;
 			last_abbrev_val = abbrev_val;
 		}
-		else if (abbrev_val == last_abbrev_val &&
+		else if (abbrev_val.value == last_abbrev_val.value &&
 				 DatumGetBool(FunctionCall2Coll(equalfn, PG_GET_COLLATION(), val, last_val)))
 		{
 			/* value equal to previous value, count it */
@@ -1301,8 +1301,8 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
 	int64		duplicate_count = 0;
 	OSAPerGroupState *osastate;
 	int			numDistinctCols;
-	Datum		abbrevVal = (Datum) 0;
-	Datum		abbrevOld = (Datum) 0;
+	Datum		abbrevVal = DummyDatum;
+	Datum		abbrevOld = DummyDatum;
 	TupleTableSlot *slot;
 	TupleTableSlot *extraslot;
 	TupleTableSlot *slot2;
@@ -1404,7 +1404,7 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
 		econtext->ecxt_innertuple = slot2;
 
 		if (!TupIsNull(slot2) &&
-			abbrevVal == abbrevOld &&
+			abbrevVal.value == abbrevOld.value &&
 			ExecQualAndReset(compareTuple, econtext))
 			duplicate_count++;
 
diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c
index 12de2446f5b..ea4af20c443 100644
--- a/src/backend/utils/adt/pg_lsn.c
+++ b/src/backend/utils/adt/pg_lsn.c
@@ -68,7 +68,7 @@ pg_lsn_in(PG_FUNCTION_ARGS)
 
 	result = pg_lsn_in_internal(str, &have_error);
 	if (have_error)
-		ereturn(fcinfo->context, (Datum) 0,
+		ereturn(fcinfo->context, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"pg_lsn", str)));
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 1c12ddbae49..b8243b2f64e 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -321,7 +321,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -682,7 +682,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 
@@ -1567,7 +1567,7 @@ pg_stat_get_io(PG_FUNCTION_ARGS)
 								backends_io_stats->stat_reset_timestamp);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -1589,7 +1589,7 @@ pg_stat_get_backend_io(PG_FUNCTION_ARGS)
 	backend_stats = pgstat_fetch_stat_backend_by_pid(pid, &bktype);
 
 	if (!backend_stats)
-		return (Datum) 0;
+		return DummyDatum;
 
 	bktype_stats = &backend_stats->io_stats;
 
@@ -1603,7 +1603,7 @@ pg_stat_get_backend_io(PG_FUNCTION_ARGS)
 	/* save tuples with data from this PgStat_BktypeIO */
 	pg_stat_io_build_tuples(rsinfo, bktype_stats, bktype,
 							backend_stats->stat_reset_timestamp);
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
@@ -1740,7 +1740,7 @@ pg_stat_get_slru(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 #define PG_STAT_GET_XACT_RELENTRY_INT64(stat)			\
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index 15398c72ea0..fd8d6b7172d 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -222,7 +222,7 @@ range_recv(PG_FUNCTION_ARGS)
 		pfree(bound_buf.data);
 	}
 	else
-		lower.val = (Datum) 0;
+		lower.val = DummyDatum;
 
 	if (RANGE_HAS_UBOUND(flags))
 	{
@@ -240,7 +240,7 @@ range_recv(PG_FUNCTION_ARGS)
 		pfree(bound_buf.data);
 	}
 	else
-		upper.val = (Datum) 0;
+		upper.val = DummyDatum;
 
 	pq_getmsgend(buf);
 
@@ -386,12 +386,12 @@ range_constructor2(PG_FUNCTION_ARGS)
 
 	typcache = range_get_typcache(fcinfo, rngtypid);
 
-	lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
+	lower.val = PG_ARGISNULL(0) ? DummyDatum : arg1;
 	lower.infinite = PG_ARGISNULL(0);
 	lower.inclusive = true;
 	lower.lower = true;
 
-	upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
+	upper.val = PG_ARGISNULL(1) ? DummyDatum : arg2;
 	upper.infinite = PG_ARGISNULL(1);
 	upper.inclusive = false;
 	upper.lower = false;
@@ -423,12 +423,12 @@ range_constructor3(PG_FUNCTION_ARGS)
 
 	flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));
 
-	lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
+	lower.val = PG_ARGISNULL(0) ? DummyDatum : arg1;
 	lower.infinite = PG_ARGISNULL(0);
 	lower.inclusive = (flags & RANGE_LB_INC) != 0;
 	lower.lower = true;
 
-	upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
+	upper.val = PG_ARGISNULL(1) ? DummyDatum : arg2;
 	upper.infinite = PG_ARGISNULL(1);
 	upper.inclusive = (flags & RANGE_UB_INC) != 0;
 	upper.lower = false;
@@ -1343,9 +1343,9 @@ range_fast_cmp(Datum a, Datum b, SortSupport ssup)
 			cmp = range_cmp_bounds(typcache, &upper1, &upper2);
 	}
 
-	if ((Datum) range_a != a)
+	if (PointerGetDatum(range_a).value != a.value)
 		pfree(range_a);
-	if ((Datum) range_b != b)
+	if (PointerGetDatum(range_b).value != b.value)
 		pfree(range_b);
 
 	return cmp;
@@ -1545,7 +1545,7 @@ int4range_canonical(PG_FUNCTION_ARGS)
 
 		/* Handle possible overflow manually */
 		if (unlikely(bnd == PG_INT32_MAX))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("integer out of range")));
 		lower.val = Int32GetDatum(bnd + 1);
@@ -1558,7 +1558,7 @@ int4range_canonical(PG_FUNCTION_ARGS)
 
 		/* Handle possible overflow manually */
 		if (unlikely(bnd == PG_INT32_MAX))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("integer out of range")));
 		upper.val = Int32GetDatum(bnd + 1);
@@ -1592,7 +1592,7 @@ int8range_canonical(PG_FUNCTION_ARGS)
 
 		/* Handle possible overflow manually */
 		if (unlikely(bnd == PG_INT64_MAX))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("bigint out of range")));
 		lower.val = Int64GetDatum(bnd + 1);
@@ -1605,7 +1605,7 @@ int8range_canonical(PG_FUNCTION_ARGS)
 
 		/* Handle possible overflow manually */
 		if (unlikely(bnd == PG_INT64_MAX))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 					 errmsg("bigint out of range")));
 		upper.val = Int64GetDatum(bnd + 1);
@@ -1641,7 +1641,7 @@ daterange_canonical(PG_FUNCTION_ARGS)
 		/* Check for overflow -- note we already eliminated PG_INT32_MAX */
 		bnd++;
 		if (unlikely(!IS_VALID_DATE(bnd)))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 					 errmsg("date out of range")));
 		lower.val = DateADTGetDatum(bnd);
@@ -1656,7 +1656,7 @@ daterange_canonical(PG_FUNCTION_ARGS)
 		/* Check for overflow -- note we already eliminated PG_INT32_MAX */
 		bnd++;
 		if (unlikely(!IS_VALID_DATE(bnd)))
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 					 errmsg("date out of range")));
 		upper.val = DateADTGetDatum(bnd);
@@ -1948,7 +1948,7 @@ range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
 		ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
 	}
 	else
-		lbound = (Datum) 0;
+		lbound = DummyDatum;
 
 	/* fetch upper bound, if any */
 	if (RANGE_HAS_UBOUND(flags))
@@ -1958,7 +1958,7 @@ range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
 		/* no need for att_addlength_pointer */
 	}
 	else
-		ubound = (Datum) 0;
+		ubound = DummyDatum;
 
 	/* emit results */
 
@@ -2229,12 +2229,12 @@ make_empty_range(TypeCacheEntry *typcache)
 	RangeBound	lower;
 	RangeBound	upper;
 
-	lower.val = (Datum) 0;
+	lower.val = DummyDatum;
 	lower.infinite = false;
 	lower.inclusive = false;
 	lower.lower = true;
 
-	upper.val = (Datum) 0;
+	upper.val = DummyDatum;
 	upper.infinite = false;
 	upper.inclusive = false;
 	upper.lower = false;
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index 6e2864cbbda..772a52d7d90 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -1662,7 +1662,7 @@ build_regexp_match_result(regexp_matches_ctx *matchctx)
 
 		if (so < 0 || eo < 0)
 		{
-			elems[i] = (Datum) 0;
+			elems[i] = DummyDatum;
 			nulls[i] = true;
 		}
 		else if (buf)
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index b8bbe95e82e..5518404a186 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -96,11 +96,11 @@ regprocin(PG_FUNCTION_ARGS)
 	clist = FuncnameGetCandidates(names, -1, NIL, false, false, false, true);
 
 	if (clist == NULL)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
 				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
 	else if (clist->next != NULL)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
 				 errmsg("more than one function named \"%s\"",
 						pro_name_or_oid)));
@@ -261,7 +261,7 @@ regprocedurein(PG_FUNCTION_ARGS)
 	}
 
 	if (clist == NULL)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
 				 errmsg("function \"%s\" does not exist", pro_name_or_oid)));
 
@@ -505,11 +505,11 @@ regoperin(PG_FUNCTION_ARGS)
 	clist = OpernameGetCandidates(names, '\0', true);
 
 	if (clist == NULL)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
 				 errmsg("operator does not exist: %s", opr_name_or_oid)));
 	else if (clist->next != NULL)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
 				 errmsg("more than one operator named %s",
 						opr_name_or_oid)));
@@ -666,12 +666,12 @@ regoperatorin(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 
 	if (nargs == 1)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_PARAMETER),
 				 errmsg("missing argument"),
 				 errhint("Use NONE to denote the missing argument of a unary operator.")));
 	if (nargs != 2)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
 				 errmsg("too many arguments"),
 				 errhint("Provide two argument types for operator.")));
@@ -679,7 +679,7 @@ regoperatorin(PG_FUNCTION_ARGS)
 	result = OpernameGetOprid(names, argtypes[0], argtypes[1]);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
 				 errmsg("operator does not exist: %s", opr_name_or_oid)));
 
@@ -909,7 +909,7 @@ regclassin(PG_FUNCTION_ARGS)
 	result = RangeVarGetRelid(makeRangeVarFromNameList(names), NoLock, true);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_TABLE),
 				 errmsg("relation \"%s\" does not exist",
 						NameListToString(names))));
@@ -1052,7 +1052,7 @@ regcollationin(PG_FUNCTION_ARGS)
 	result = get_collation_oid(names, true);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("collation \"%s\" for encoding \"%s\" does not exist",
 						NameListToString(names), GetDatabaseEncodingName())));
@@ -1345,7 +1345,7 @@ regconfigin(PG_FUNCTION_ARGS)
 	result = get_ts_config_oid(names, true);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("text search configuration \"%s\" does not exist",
 						NameListToString(names))));
@@ -1455,7 +1455,7 @@ regdictionaryin(PG_FUNCTION_ARGS)
 	result = get_ts_dict_oid(names, true);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("text search dictionary \"%s\" does not exist",
 						NameListToString(names))));
@@ -1560,14 +1560,14 @@ regrolein(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 
 	if (list_length(names) != 1)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_NAME),
 				 errmsg("invalid name syntax")));
 
 	result = get_role_oid(strVal(linitial(names)), true);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("role \"%s\" does not exist",
 						strVal(linitial(names)))));
@@ -1677,14 +1677,14 @@ regnamespacein(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 
 	if (list_length(names) != 1)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_NAME),
 				 errmsg("invalid name syntax")));
 
 	result = get_namespace_oid(strVal(linitial(names)), true);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_SCHEMA),
 				 errmsg("schema \"%s\" does not exist",
 						strVal(linitial(names)))));
@@ -1794,14 +1794,14 @@ regdatabasein(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 
 	if (list_length(names) != 1)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_NAME),
 				 errmsg("invalid name syntax")));
 
 	result = get_database_oid(strVal(linitial(names)), true);
 
 	if (!OidIsValid(result))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("database \"%s\" does not exist",
 						strVal(linitial(names)))));
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 059fc5ebf60..2f1f8ad50b9 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -2868,7 +2868,7 @@ ri_InitHashTables(void)
 	/* Arrange to flush cache on pg_constraint changes */
 	CacheRegisterSyscacheCallback(CONSTROID,
 								  InvalidateConstraintCacheCallBack,
-								  (Datum) 0);
+								  DummyDatum);
 
 	ctl.keysize = sizeof(RI_QueryKey);
 	ctl.entrysize = sizeof(RI_QueryHashEntry);
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 9e5449f17d7..8dfca44c669 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -100,7 +100,7 @@ record_in(PG_FUNCTION_ARGS)
 	 * supply a valid typmod, and then we can do something useful for RECORD.
 	 */
 	if (tupType == RECORDOID && tupTypmod < 0)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("input of anonymous composite types is not implemented")));
 
@@ -172,7 +172,7 @@ record_in(PG_FUNCTION_ARGS)
 		/* Ignore dropped columns in datatype, but fill with nulls */
 		if (att->attisdropped)
 		{
-			values[i] = (Datum) 0;
+			values[i] = DummyDatum;
 			nulls[i] = true;
 			continue;
 		}
@@ -572,7 +572,7 @@ record_recv(PG_FUNCTION_ARGS)
 		/* Ignore dropped columns in datatype, but fill with nulls */
 		if (att->attisdropped)
 		{
-			values[i] = (Datum) 0;
+			values[i] = DummyDatum;
 			nulls[i] = true;
 			continue;
 		}
@@ -1502,8 +1502,8 @@ record_image_cmp(FunctionCallInfo fcinfo)
 			/* Compare the pair of elements */
 			if (att1->attbyval)
 			{
-				if (values1[i1] != values2[i2])
-					cmpresult = (values1[i1] < values2[i2]) ? -1 : 1;
+				if (values1[i1].value != values2[i2].value)
+					cmpresult = (values1[i1].value < values2[i2].value) ? -1 : 1;
 			}
 			else if (att1->attlen > 0)
 			{
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 3d6e6bdbfd2..53ee62f827a 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1462,7 +1462,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
 			int16		opt = indoption->values[keyno];
 			Oid			indcoll = indcollation->values[keyno];
 			Datum		attoptions = get_attoptions(indexrelid, keyno + 1);
-			bool		has_options = attoptions != (Datum) 0;
+			bool		has_options = attoptions.value != DummyDatum.value;
 
 			/* Add collation, if not default for column */
 			if (OidIsValid(indcoll) && indcoll != keycolcollation)
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 17fbfa9b410..d799479bf18 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -6292,8 +6292,8 @@ get_variable_range(PlannerInfo *root, VariableStatData *vardata,
 				   Oid sortop, Oid collation,
 				   Datum *min, Datum *max)
 {
-	Datum		tmin = 0;
-	Datum		tmax = 0;
+	Datum		tmin = DummyDatum;
+	Datum		tmax = DummyDatum;
 	bool		have_data = false;
 	int16		typLen;
 	bool		typByVal;
@@ -6590,7 +6590,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
 								   InvalidOid,	/* no strategy subtype */
 								   InvalidOid,	/* no collation */
 								   InvalidOid,	/* no reg proc for this */
-								   (Datum) 0);	/* constant */
+								   DummyDatum);	/* constant */
 
 			/* If min is requested ... */
 			if (min)
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index 39dab3e42df..b9a87d3173c 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -67,7 +67,7 @@ tidin(PG_FUNCTION_ARGS)
 			coord[i++] = p + 1;
 
 	if (i < NTIDARGS)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"tid", str)));
@@ -75,7 +75,7 @@ tidin(PG_FUNCTION_ARGS)
 	errno = 0;
 	cvt = strtoul(coord[0], &badp, 10);
 	if (errno || *badp != DELIM)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"tid", str)));
@@ -89,7 +89,7 @@ tidin(PG_FUNCTION_ARGS)
 #if SIZEOF_LONG > 4
 	if (cvt != (unsigned long) blockNumber &&
 		cvt != (unsigned long) ((int32) blockNumber))
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"tid", str)));
@@ -98,7 +98,7 @@ tidin(PG_FUNCTION_ARGS)
 	cvt = strtoul(coord[1], &badp, 10);
 	if (errno || *badp != RDELIM ||
 		cvt > USHRT_MAX)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"tid", str)));
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index e640b48205b..3fb9a17eb03 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -199,7 +199,7 @@ timestamp_in(PG_FUNCTION_ARGS)
 	{
 		case DTK_DATE:
 			if (tm2timestamp(tm, fsec, NULL, &result) != 0)
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("timestamp out of range: \"%s\"", str)));
 			break;
@@ -452,7 +452,7 @@ timestamptz_in(PG_FUNCTION_ARGS)
 	{
 		case DTK_DATE:
 			if (tm2timestamp(tm, fsec, &tz, &result) != 0)
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("timestamp out of range: \"%s\"", str)));
 			break;
@@ -943,7 +943,7 @@ interval_in(PG_FUNCTION_ARGS)
 	{
 		case DTK_DELTA:
 			if (itmin2interval(itm_in, result) != 0)
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("interval out of range")));
 			break;
@@ -2315,7 +2315,7 @@ timestamp_decrement(Relation rel, Datum existing, bool *underflow)
 	{
 		/* return value is undefined */
 		*underflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*underflow = false;
@@ -2332,7 +2332,7 @@ timestamp_increment(Relation rel, Datum existing, bool *overflow)
 	{
 		/* return value is undefined */
 		*overflow = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	*overflow = false;
diff --git a/src/backend/utils/adt/tsvector.c b/src/backend/utils/adt/tsvector.c
index 1fa2e3729bf..9c84584bcef 100644
--- a/src/backend/utils/adt/tsvector.c
+++ b/src/backend/utils/adt/tsvector.c
@@ -208,14 +208,14 @@ tsvectorin(PG_FUNCTION_ARGS)
 	while (gettoken_tsvector(state, &token, &toklen, &pos, &poslen, NULL))
 	{
 		if (toklen >= MAXSTRLEN)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("word is too long (%ld bytes, max %ld bytes)",
 							(long) toklen,
 							(long) (MAXSTRLEN - 1))));
 
 		if (cur - tmpbuf > MAXSTRPOS)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("string is too long for tsvector (%ld bytes, max %ld bytes)",
 							(long) (cur - tmpbuf), (long) MAXSTRPOS)));
@@ -269,7 +269,7 @@ tsvectorin(PG_FUNCTION_ARGS)
 		buflen = 0;
 
 	if (buflen > MAXSTRPOS)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("string is too long for tsvector (%d bytes, max %d bytes)", buflen, MAXSTRPOS)));
 
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index 0625da9532f..fb2cd1206a4 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -2568,7 +2568,7 @@ ts_process_call(FuncCallContext *funcctx)
 		return result;
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 static TSVectorStat *
@@ -2680,7 +2680,8 @@ ts_stat1(PG_FUNCTION_ARGS)
 	}
 
 	funcctx = SRF_PERCALL_SETUP();
-	if ((result = ts_process_call(funcctx)) != (Datum) 0)
+	result = ts_process_call(funcctx);
+	if (result.value != DummyDatum.value)
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -2707,7 +2708,8 @@ ts_stat2(PG_FUNCTION_ARGS)
 	}
 
 	funcctx = SRF_PERCALL_SETUP();
-	if ((result = ts_process_call(funcctx)) != (Datum) 0)
+	result = ts_process_call(funcctx);
+	if (result.value != DummyDatum.value)
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
index bce7309c183..2203400de79 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -399,9 +399,9 @@ uuid_abbrev_convert(Datum original, SortSupport ssup)
 		uint32		tmp;
 
 #if SIZEOF_DATUM == 8
-		tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
+		tmp = (uint32) res.value ^ (uint32) ((uint64) res.value >> 32);
 #else							/* SIZEOF_DATUM != 8 */
-		tmp = (uint32) res;
+		tmp = (uint32) res.value;
 #endif
 
 		addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
@@ -415,7 +415,7 @@ uuid_abbrev_convert(Datum original, SortSupport ssup)
 	 * this, the comparator would have to call memcmp() with a pair of
 	 * pointers to the first byte of each abbreviated key, which is slower.
 	 */
-	res = DatumBigEndianToNative(res);
+	res.value = DatumBigEndianToNative(res);
 
 	return res;
 }
@@ -442,7 +442,7 @@ uuid_decrement(Relation rel, Datum existing, bool *underflow)
 
 	/* return value is undefined */
 	*underflow = true;
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 static Datum
@@ -467,7 +467,7 @@ uuid_increment(Relation rel, Datum existing, bool *overflow)
 
 	/* return value is undefined */
 	*overflow = true;
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 Datum
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index 205a67dafc5..6ba42a6a48c 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -193,7 +193,7 @@ bit_in(PG_FUNCTION_ARGS)
 	else
 	{
 		if (slen > VARBITMAXLEN / 4)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("bit string length exceeds the maximum allowed (%d)",
 							VARBITMAXLEN)));
@@ -207,7 +207,7 @@ bit_in(PG_FUNCTION_ARGS)
 	if (atttypmod <= 0)
 		atttypmod = bitlen;
 	else if (bitlen != atttypmod)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
 				 errmsg("bit string length %d does not match type bit(%d)",
 						bitlen, atttypmod)));
@@ -229,7 +229,7 @@ bit_in(PG_FUNCTION_ARGS)
 			if (*sp == '1')
 				*r |= x;
 			else if (*sp != '0')
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("\"%.*s\" is not a valid binary digit",
 								pg_mblen(sp), sp)));
@@ -254,7 +254,7 @@ bit_in(PG_FUNCTION_ARGS)
 			else if (*sp >= 'a' && *sp <= 'f')
 				x = (bits8) (*sp - 'a') + 10;
 			else
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("\"%.*s\" is not a valid hexadecimal digit",
 								pg_mblen(sp), sp)));
@@ -494,7 +494,7 @@ varbit_in(PG_FUNCTION_ARGS)
 	else
 	{
 		if (slen > VARBITMAXLEN / 4)
-			ereturn(escontext, (Datum) 0,
+			ereturn(escontext, DummyDatum,
 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 					 errmsg("bit string length exceeds the maximum allowed (%d)",
 							VARBITMAXLEN)));
@@ -508,7 +508,7 @@ varbit_in(PG_FUNCTION_ARGS)
 	if (atttypmod <= 0)
 		atttypmod = bitlen;
 	else if (bitlen > atttypmod)
-		ereturn(escontext, (Datum) 0,
+		ereturn(escontext, DummyDatum,
 				(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 				 errmsg("bit string too long for type bit varying(%d)",
 						atttypmod)));
@@ -530,7 +530,7 @@ varbit_in(PG_FUNCTION_ARGS)
 			if (*sp == '1')
 				*r |= x;
 			else if (*sp != '0')
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("\"%.*s\" is not a valid binary digit",
 								pg_mblen(sp), sp)));
@@ -555,7 +555,7 @@ varbit_in(PG_FUNCTION_ARGS)
 			else if (*sp >= 'a' && *sp <= 'f')
 				x = (bits8) (*sp - 'a') + 10;
 			else
-				ereturn(escontext, (Datum) 0,
+				ereturn(escontext, DummyDatum,
 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 						 errmsg("\"%.*s\" is not a valid hexadecimal digit",
 								pg_mblen(sp), sp)));
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 11b442a5941..60dde5a30ef 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -1770,9 +1770,9 @@ varstrfastcmp_c(Datum x, Datum y, SortSupport ssup)
 		result = (len1 < len2) ? -1 : 1;
 
 	/* We can't afford to leak memory here. */
-	if (PointerGetDatum(arg1) != x)
+	if (PointerGetDatum(arg1).value != x.value)
 		pfree(arg1);
-	if (PointerGetDatum(arg2) != y)
+	if (PointerGetDatum(arg2).value != y.value)
 		pfree(arg2);
 
 	return result;
@@ -1807,9 +1807,9 @@ bpcharfastcmp_c(Datum x, Datum y, SortSupport ssup)
 		result = (len1 < len2) ? -1 : 1;
 
 	/* We can't afford to leak memory here. */
-	if (PointerGetDatum(arg1) != x)
+	if (PointerGetDatum(arg1).value != x.value)
 		pfree(arg1);
-	if (PointerGetDatum(arg2) != y)
+	if (PointerGetDatum(arg2).value != y.value)
 		pfree(arg2);
 
 	return result;
@@ -1850,9 +1850,9 @@ varlenafastcmp_locale(Datum x, Datum y, SortSupport ssup)
 	result = varstrfastcmp_locale(a1p, len1, a2p, len2, ssup);
 
 	/* We can't afford to leak memory here. */
-	if (PointerGetDatum(arg1) != x)
+	if (PointerGetDatum(arg1).value != x.value)
 		pfree(arg1);
-	if (PointerGetDatum(arg2) != y)
+	if (PointerGetDatum(arg2).value != y.value)
 		pfree(arg2);
 
 	return result;
@@ -2137,8 +2137,8 @@ varstr_abbrev_convert(Datum original, SortSupport ssup)
 		uint32		lohalf,
 					hihalf;
 
-		lohalf = (uint32) res;
-		hihalf = (uint32) (res >> 32);
+		lohalf = (uint32) res.value;
+		hihalf = (uint32) (res.value >> 32);
 		hash = DatumGetUInt32(hash_uint32(lohalf ^ hihalf));
 	}
 #else							/* SIZEOF_DATUM != 8 */
@@ -2159,10 +2159,10 @@ varstr_abbrev_convert(Datum original, SortSupport ssup)
 	 * this, the comparator would have to call memcmp() with a pair of
 	 * pointers to the first byte of each abbreviated key, which is slower.
 	 */
-	res = DatumBigEndianToNative(res);
+	res.value = DatumBigEndianToNative(res);
 
 	/* Don't leak memory here */
-	if (PointerGetDatum(authoritative) != original)
+	if (PointerGetDatum(authoritative).value != original.value)
 		pfree(authoritative);
 
 	return res;
@@ -3663,7 +3663,7 @@ text_to_table(PG_FUNCTION_ARGS)
 
 	(void) split_text(fcinfo, &tstate);
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 /*
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 182e8f75db7..761b0f764d1 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -293,7 +293,7 @@ xml_in(PG_FUNCTION_ARGS)
 	PG_RETURN_XML_P(vardata);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif
 }
 
@@ -429,7 +429,7 @@ xml_recv(PG_FUNCTION_ARGS)
 	PG_RETURN_XML_P(result);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif
 }
 
@@ -518,7 +518,7 @@ xmlcomment(PG_FUNCTION_ARGS)
 	PG_RETURN_XML_P(stringinfo_to_xmltype(&buf));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif
 }
 
@@ -562,7 +562,7 @@ xmltext(PG_FUNCTION_ARGS)
 	PG_RETURN_XML_P(result);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif							/* not USE_LIBXML */
 }
 
@@ -1160,7 +1160,7 @@ xmlvalidate(PG_FUNCTION_ARGS)
 	ereport(ERROR,
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("xmlvalidate is not implemented")));
-	return 0;
+	PG_RETURN_DUMMY();
 }
 
 
@@ -4578,7 +4578,7 @@ xpath(PG_FUNCTION_ARGS)
 	PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif
 }
 
@@ -4600,7 +4600,7 @@ xmlexists(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(res_nitems > 0);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif
 }
 
@@ -4624,7 +4624,7 @@ xpath_exists(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(res_nitems > 0);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif
 }
 
@@ -4660,7 +4660,7 @@ xml_is_well_formed(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(wellformed_xml(data, xmloption));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif							/* not USE_LIBXML */
 }
 
@@ -4673,7 +4673,7 @@ xml_is_well_formed_document(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(wellformed_xml(data, XMLOPTION_DOCUMENT));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif							/* not USE_LIBXML */
 }
 
@@ -4686,7 +4686,7 @@ xml_is_well_formed_content(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(wellformed_xml(data, XMLOPTION_CONTENT));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif							/* not USE_LIBXML */
 }
 
@@ -4974,7 +4974,7 @@ XmlTableGetValue(TableFuncScanState *state, int colnum,
 				 Oid typid, int32 typmod, bool *isnull)
 {
 #ifdef USE_LIBXML
-	Datum		result = (Datum) 0;
+	Datum		result = DummyDatum;
 	XmlTableBuilderData *xtCxt;
 	volatile xmlXPathObjectPtr xpathobj = NULL;
 
@@ -5113,7 +5113,7 @@ XmlTableGetValue(TableFuncScanState *state, int colnum,
 	return result;
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return DummyDatum;
 #endif							/* not USE_LIBXML */
 }
 
diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c
index 45d1e2be007..bf5c702a5cd 100644
--- a/src/backend/utils/cache/attoptcache.c
+++ b/src/backend/utils/cache/attoptcache.c
@@ -120,7 +120,7 @@ InitializeAttoptCache(void)
 	/* Watch for invalidation events. */
 	CacheRegisterSyscacheCallback(ATTNUM,
 								  InvalidateAttoptCacheCallback,
-								  (Datum) 0);
+								  DummyDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index e2cd3feaf81..097d3f48992 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -386,10 +386,10 @@ CatalogCacheComputeHashValue(CatCache *cache, int nkeys,
 static uint32
 CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
 {
-	Datum		v1 = 0,
-				v2 = 0,
-				v3 = 0,
-				v4 = 0;
+	Datum		v1 = DummyDatum,
+				v2 = DummyDatum,
+				v3 = DummyDatum,
+				v4 = DummyDatum;
 	bool		isNull = false;
 	int		   *cc_keyno = cache->cc_keyno;
 	TupleDesc	cc_tupdesc = cache->cc_tupdesc;
@@ -1358,7 +1358,7 @@ HeapTuple
 SearchCatCache1(CatCache *cache,
 				Datum v1)
 {
-	return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
+	return SearchCatCacheInternal(cache, 1, v1, DummyDatum, DummyDatum, DummyDatum);
 }
 
 
@@ -1366,7 +1366,7 @@ HeapTuple
 SearchCatCache2(CatCache *cache,
 				Datum v1, Datum v2)
 {
-	return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
+	return SearchCatCacheInternal(cache, 2, v1, v2, DummyDatum, DummyDatum);
 }
 
 
@@ -1374,7 +1374,7 @@ HeapTuple
 SearchCatCache3(CatCache *cache,
 				Datum v1, Datum v2, Datum v3)
 {
-	return SearchCatCacheInternal(cache, 3, v1, v2, v3, 0);
+	return SearchCatCacheInternal(cache, 3, v1, v2, v3, DummyDatum);
 }
 
 
@@ -1723,7 +1723,7 @@ SearchCatCacheList(CatCache *cache,
 				   Datum v2,
 				   Datum v3)
 {
-	Datum		v4 = 0;			/* dummy last-column value */
+	Datum		v4 = DummyDatum;			/* dummy last-column value */
 	Datum		arguments[CATCACHE_MAXKEYS];
 	uint32		lHashValue;
 	Index		lHashIndex;
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index ce596bf5638..e4f10158c71 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -107,7 +107,7 @@ BuildEventTriggerCache(void)
 								  ALLOCSET_DEFAULT_SIZES);
 		CacheRegisterSyscacheCallback(EVENTTRIGGEROID,
 									  InvalidateEventCacheCallback,
-									  (Datum) 0);
+									  DummyDatum);
 	}
 
 	/* Switch to correct memory context. */
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 032bb6222c4..e85041e34b7 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -1078,7 +1078,7 @@ get_attoptions(Oid relid, int16 attnum)
 							  &isnull);
 
 	if (isnull)
-		result = (Datum) 0;
+		result = DummyDatum;
 	else
 		result = datumCopy(attopts, false, -1); /* text[] */
 
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 0c506d320b1..05519bec9b6 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -145,14 +145,14 @@ int			plan_cache_mode = PLAN_CACHE_MODE_AUTO;
 void
 InitPlanCache(void)
 {
-	CacheRegisterRelcacheCallback(PlanCacheRelCallback, (Datum) 0);
-	CacheRegisterSyscacheCallback(PROCOID, PlanCacheObjectCallback, (Datum) 0);
-	CacheRegisterSyscacheCallback(TYPEOID, PlanCacheObjectCallback, (Datum) 0);
-	CacheRegisterSyscacheCallback(NAMESPACEOID, PlanCacheSysCallback, (Datum) 0);
-	CacheRegisterSyscacheCallback(OPEROID, PlanCacheSysCallback, (Datum) 0);
-	CacheRegisterSyscacheCallback(AMOPOPID, PlanCacheSysCallback, (Datum) 0);
-	CacheRegisterSyscacheCallback(FOREIGNSERVEROID, PlanCacheSysCallback, (Datum) 0);
-	CacheRegisterSyscacheCallback(FOREIGNDATAWRAPPEROID, PlanCacheSysCallback, (Datum) 0);
+	CacheRegisterRelcacheCallback(PlanCacheRelCallback, DummyDatum);
+	CacheRegisterSyscacheCallback(PROCOID, PlanCacheObjectCallback, DummyDatum);
+	CacheRegisterSyscacheCallback(TYPEOID, PlanCacheObjectCallback, DummyDatum);
+	CacheRegisterSyscacheCallback(NAMESPACEOID, PlanCacheSysCallback, DummyDatum);
+	CacheRegisterSyscacheCallback(OPEROID, PlanCacheSysCallback, DummyDatum);
+	CacheRegisterSyscacheCallback(AMOPOPID, PlanCacheSysCallback, DummyDatum);
+	CacheRegisterSyscacheCallback(FOREIGNSERVEROID, PlanCacheSysCallback, DummyDatum);
+	CacheRegisterSyscacheCallback(FOREIGNDATAWRAPPEROID, PlanCacheSysCallback, DummyDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 6fe268a8eec..83a2d5c4747 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5188,7 +5188,7 @@ RelationGetDummyIndexExpressions(Relation relation)
 								   exprTypmod(rawExpr),
 								   exprCollation(rawExpr),
 								   1,
-								   (Datum) 0,
+								   DummyDatum,
 								   true,
 								   true));
 	}
@@ -6009,7 +6009,7 @@ RelationGetIndexAttOptions(Relation relation, bool copy)
 
 			opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
 
-			if (attoptions != (Datum) 0)
+			if (DatumGetPointer(attoptions) != NULL) // XXX idea pfree_if_nonnull
 				pfree(DatumGetPointer(attoptions));
 		}
 	}
diff --git a/src/backend/utils/cache/relfilenumbermap.c b/src/backend/utils/cache/relfilenumbermap.c
index 8a2f6f8c693..0ecf2b2afee 100644
--- a/src/backend/utils/cache/relfilenumbermap.c
+++ b/src/backend/utils/cache/relfilenumbermap.c
@@ -123,7 +123,7 @@ InitializeRelfilenumberMap(void)
 
 	/* Watch for invalidation events. */
 	CacheRegisterRelcacheCallback(RelfilenumberMapInvalidateCallback,
-								  (Datum) 0);
+								  DummyDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
index 23458599298..30d8a5881e7 100644
--- a/src/backend/utils/cache/spccache.c
+++ b/src/backend/utils/cache/spccache.c
@@ -93,7 +93,7 @@ InitializeTableSpaceCache(void)
 	/* Watch for invalidation events. */
 	CacheRegisterSyscacheCallback(TABLESPACEOID,
 								  InvalidateTableSpaceCacheCallback,
-								  (Datum) 0);
+								  DummyDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index f9aec38a11f..ff674044d66 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -416,10 +416,10 @@ lookup_type_cache(Oid type_id, int flags)
 											 &ctl, HASH_ELEM | HASH_BLOBS);
 
 		/* Also set up callbacks for SI invalidations */
-		CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0);
-		CacheRegisterSyscacheCallback(TYPEOID, TypeCacheTypCallback, (Datum) 0);
-		CacheRegisterSyscacheCallback(CLAOID, TypeCacheOpcCallback, (Datum) 0);
-		CacheRegisterSyscacheCallback(CONSTROID, TypeCacheConstrCallback, (Datum) 0);
+		CacheRegisterRelcacheCallback(TypeCacheRelCallback, DummyDatum);
+		CacheRegisterSyscacheCallback(TYPEOID, TypeCacheTypCallback, DummyDatum);
+		CacheRegisterSyscacheCallback(CLAOID, TypeCacheOpcCallback, DummyDatum);
+		CacheRegisterSyscacheCallback(CONSTROID, TypeCacheConstrCallback, DummyDatum);
 
 		/* Also make sure CacheMemoryContext exists */
 		if (!CacheMemoryContext)
@@ -2283,7 +2283,7 @@ SharedRecordTypmodRegistryInit(SharedRecordTypmodRegistry *registry,
 	 * the memory, the leader process will use a shared registry until it
 	 * exits.
 	 */
-	on_dsm_detach(segment, shared_record_typmod_registry_detach, (Datum) 0);
+	on_dsm_detach(segment, shared_record_typmod_registry_detach, DummyDatum);
 }
 
 /*
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 782291d9998..37984d0f394 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -1533,7 +1533,7 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
 	Datum		result;
 
 	if (str == NULL && flinfo->fn_strict)
-		return (Datum) 0;		/* just return null result */
+		return DummyDatum;		/* just return null result */
 
 	InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
 
@@ -1591,7 +1591,7 @@ InputFunctionCallSafe(FmgrInfo *flinfo, char *str,
 
 	if (str == NULL && flinfo->fn_strict)
 	{
-		*result = (Datum) 0;	/* just return null result */
+		*result = DummyDatum;	/* just return null result */
 		return true;
 	}
 
@@ -1646,7 +1646,7 @@ DirectInputFunctionCallSafe(PGFunction func, char *str,
 
 	if (str == NULL)
 	{
-		*result = (Datum) 0;	/* just return null result */
+		*result = DummyDatum;	/* just return null result */
 		return true;
 	}
 
@@ -1701,7 +1701,7 @@ ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
 	Datum		result;
 
 	if (buf == NULL && flinfo->fn_strict)
-		return (Datum) 0;		/* just return null result */
+		return DummyDatum;		/* just return null result */
 
 	InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
 
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 5f2317211c9..5f38a52d648 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -1531,7 +1531,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes,
 	int			i;
 
 	/* Do nothing if null proargnames */
-	if (proargnames == PointerGetDatum(NULL))
+	if (DatumGetPointer(proargnames) == NULL)
 	{
 		*arg_names = NULL;
 		return 0;
@@ -1548,7 +1548,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes,
 		ARR_ELEMTYPE(arr) != TEXTOID)
 		elog(ERROR, "proargnames is not a 1-D text array or it contains nulls");
 	deconstruct_array_builtin(arr, TEXTOID, &argnames, NULL, &numargs);
-	if (proargmodes != PointerGetDatum(NULL))
+	if (DatumGetPointer(proargmodes) != NULL)
 	{
 		arr = DatumGetArrayTypeP(proargmodes);	/* ensure not toasted */
 		if (ARR_NDIM(arr) != 1 ||
@@ -1766,8 +1766,8 @@ build_function_result_tupdesc_d(char prokind,
 	int			i;
 
 	/* Can't have output args if columns are null */
-	if (proallargtypes == PointerGetDatum(NULL) ||
-		proargmodes == PointerGetDatum(NULL))
+	if (DatumGetPointer(proallargtypes) == NULL ||
+		DatumGetPointer(proargmodes) == NULL)
 		return NULL;
 
 	/*
@@ -1791,7 +1791,7 @@ build_function_result_tupdesc_d(char prokind,
 		elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
 			 numargs);
 	argmodes = (char *) ARR_DATA_PTR(arr);
-	if (proargnames != PointerGetDatum(NULL))
+	if (DatumGetPointer(proargnames) != NULL)
 	{
 		arr = DatumGetArrayTypeP(proargnames);	/* ensure not toasted */
 		if (ARR_NDIM(arr) != 1 ||
@@ -2072,7 +2072,7 @@ extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
 				types_res[i] = TEXTOID;
 
 				if (PG_ARGISNULL(i + variadic_start))
-					args_res[i] = (Datum) 0;
+					args_res[i] = DummyDatum;
 				else
 					args_res[i] =
 						CStringGetTextDatum(PG_GETARG_POINTER(i + variadic_start));
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 43b4dbccc3d..47afb463920 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -1491,7 +1491,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
 	 * to the list of files to unlink.
 	 */
 	if (lock_files == NIL)
-		on_proc_exit(UnlinkLockFiles, 0);
+		on_proc_exit(UnlinkLockFiles, DummyDatum);
 
 	/*
 	 * Use lcons so that the lock files are unlinked in reverse order of
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 641e535a73c..432508d1166 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -793,8 +793,8 @@ InitPostgres(const char *in_dbname, Oid dboid,
 		 * Use before_shmem_exit() so that ShutdownXLOG() can rely on DSM
 		 * segments etc to work (which in turn is required for pgstats).
 		 */
-		before_shmem_exit(pgstat_before_server_shutdown, 0);
-		before_shmem_exit(ShutdownXLOG, 0);
+		before_shmem_exit(pgstat_before_server_shutdown, DummyDatum);
+		before_shmem_exit(ShutdownXLOG, DummyDatum);
 	}
 
 	/*
@@ -825,7 +825,7 @@ InitPostgres(const char *in_dbname, Oid dboid,
 	 * initialization transaction, as is entirely possible, we need the
 	 * AbortTransaction call to clean up.
 	 */
-	before_shmem_exit(ShutdownPostgres, 0);
+	before_shmem_exit(ShutdownPostgres, DummyDatum);
 
 	/* The autovacuum launcher is done here */
 	if (AmAutoVacuumLauncherProcess())
diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c
index b9e26982abd..22783e7dda3 100644
--- a/src/backend/utils/misc/guc_funcs.c
+++ b/src/backend/utils/misc/guc_funcs.c
@@ -1043,5 +1043,5 @@ show_all_file_settings(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/utils/misc/pg_config.c b/src/backend/utils/misc/pg_config.c
index e64e6758c93..acef79d45e6 100644
--- a/src/backend/utils/misc/pg_config.c
+++ b/src/backend/utils/misc/pg_config.c
@@ -45,5 +45,5 @@ pg_config(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 5858b0af64c..0887c08d892 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -84,7 +84,7 @@ superuser_arg(Oid roleid)
 	{
 		CacheRegisterSyscacheCallback(AUTHOID,
 									  RoleidCallback,
-									  (Datum) 0);
+									  DummyDatum);
 		roleid_callback_registered = true;
 	}
 
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 0be1c2b0fff..51b314c2b88 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -1164,7 +1164,7 @@ pg_cursor(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 }
 
 bool
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index d39f3e1b655..68ceab4bc37 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -232,9 +232,9 @@ hash_resource_elem(Datum value, const ResourceOwnerDesc *kind)
 	 * result enough for our purposes.
 	 */
 #if SIZEOF_DATUM == 8
-	return hash_combine64(murmurhash64((uint64) value), (uint64) kind);
+	return hash_combine64(murmurhash64((uint64) value.value), (uint64) kind);
 #else
-	return hash_combine(murmurhash32((uint32) value), (uint32) kind);
+	return hash_combine(murmurhash32((uint32) value.value), (uint32) kind);
 #endif
 }
 
@@ -575,7 +575,7 @@ ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *k
 	/* Search through all items in the array first. */
 	for (int i = owner->narr - 1; i >= 0; i--)
 	{
-		if (owner->arr[i].item == value &&
+		if (owner->arr[i].item.value == value.value &&
 			owner->arr[i].kind == kind)
 		{
 			owner->arr[i] = owner->arr[owner->narr - 1];
@@ -597,10 +597,10 @@ ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *k
 		idx = hash_resource_elem(value, kind) & mask;
 		for (uint32 i = 0; i < owner->capacity; i++)
 		{
-			if (owner->hash[idx].item == value &&
+			if (owner->hash[idx].item.value == value.value &&
 				owner->hash[idx].kind == kind)
 			{
-				owner->hash[idx].item = (Datum) 0;
+				owner->hash[idx].item = DummyDatum;
 				owner->hash[idx].kind = NULL;
 				owner->nhash--;
 
@@ -851,7 +851,7 @@ ResourceOwnerReleaseAllOfKind(ResourceOwner owner, const ResourceOwnerDesc *kind
 		{
 			Datum		value = owner->hash[i].item;
 
-			owner->hash[i].item = (Datum) 0;
+			owner->hash[i].item = DummyDatum;
 			owner->hash[i].kind = NULL;
 			owner->nhash--;
 
@@ -1007,7 +1007,7 @@ CreateAuxProcessResourceOwner(void)
 	 * Register a shmem-exit callback for cleanup of aux-process resource
 	 * owner.  (This needs to run after, e.g., ShutdownXLOG.)
 	 */
-	on_shmem_exit(ReleaseAuxProcessResourcesCallback, 0);
+	on_shmem_exit(ReleaseAuxProcessResourcesCallback, DummyDatum);
 }
 
 /*
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 65ab83fff8b..55373a1464b 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -3138,9 +3138,9 @@ free_sort_tuple(Tuplesortstate *state, SortTuple *stup)
 int
 ssup_datum_unsigned_cmp(Datum x, Datum y, SortSupport ssup)
 {
-	if (x < y)
+	if (x.value < y.value)
 		return -1;
-	else if (x > y)
+	else if (x.value > y.value)
 		return 1;
 	else
 		return 0;
diff --git a/src/backend/utils/sort/tuplesortvariants.c b/src/backend/utils/sort/tuplesortvariants.c
index c5d18e46716..2636a9d090e 100644
--- a/src/backend/utils/sort/tuplesortvariants.c
+++ b/src/backend/utils/sort/tuplesortvariants.c
@@ -896,7 +896,7 @@ tuplesort_putgintuple(Tuplesortstate *state, GinTuple *tuple, Size size)
 	memcpy(ctup, tuple, size);
 
 	stup.tuple = ctup;
-	stup.datum1 = (Datum) 0;
+	stup.datum1 = DummyDatum;
 	stup.isnull1 = false;
 
 	/* GetMemoryChunkSpace is not supported for bump contexts */
@@ -944,7 +944,7 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
 		 * Set datum1 to zeroed representation for NULLs (to be consistent,
 		 * and to support cheap inequality tests for NULL abbreviated keys).
 		 */
-		stup.datum1 = !isNull ? val : (Datum) 0;
+		stup.datum1 = !isNull ? val : DummyDatum;
 		stup.isnull1 = isNull;
 		stup.tuple = NULL;		/* no separate storage */
 	}
@@ -1956,7 +1956,7 @@ readtup_index_gin(Tuplesortstate *state, SortTuple *stup,
 	stup->tuple = (void *) tuple;
 
 	/* no abbreviations (FIXME maybe use attrnum for this?) */
-	stup->datum1 = (Datum) 0;
+	stup->datum1 = DummyDatum;
 }
 
 /*
@@ -2046,7 +2046,7 @@ readtup_datum(Tuplesortstate *state, SortTuple *stup,
 	if (tuplen == 0)
 	{
 		/* it's NULL */
-		stup->datum1 = (Datum) 0;
+		stup->datum1 = DummyDatum;
 		stup->isnull1 = true;
 		stup->tuple = NULL;
 	}
diff --git a/src/include/access/gin.h b/src/include/access/gin.h
index 2e1076a0499..26744cb8507 100644
--- a/src/include/access/gin.h
+++ b/src/include/access/gin.h
@@ -81,13 +81,13 @@ StaticAssertDecl(sizeof(GinTernaryValue) == sizeof(bool),
 static inline GinTernaryValue
 DatumGetGinTernaryValue(Datum X)
 {
-	return (GinTernaryValue) X;
+	return (GinTernaryValue) X.value;
 }
 
 static inline Datum
 GinTernaryValueGetDatum(GinTernaryValue X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 #define PG_RETURN_GIN_TERNARY_VALUE(x) return GinTernaryValueGetDatum(x)
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index aa957cf3b01..62678703347 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -884,7 +884,7 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
 		if (att_isnull(attnum - 1, tup->t_data->t_bits))
 		{
 			*isnull = true;
-			return (Datum) NULL;
+			return DummyDatum;
 		}
 		else
 			return nocachegetattr(tup, attnum, tupleDesc);
diff --git a/src/include/access/itup.h b/src/include/access/itup.h
index 7066c2a2868..d976d9e0dbd 100644
--- a/src/include/access/itup.h
+++ b/src/include/access/itup.h
@@ -154,7 +154,7 @@ index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
 		if (att_isnull(attnum - 1, (bits8 *) tup + sizeof(IndexTupleData)))
 		{
 			*isnull = true;
-			return (Datum) NULL;
+			return DummyDatum;
 		}
 		else
 			return nocache_index_getattr(tup, attnum, tupleDesc);
diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h
index cb43a278f46..ade1b769b45 100644
--- a/src/include/access/spgist_private.h
+++ b/src/include/access/spgist_private.h
@@ -315,7 +315,7 @@ typedef SpGistInnerTupleData *SpGistInnerTuple;
 							 ((s)->attPrefixType.attbyval ? \
 							  *(Datum *) _SGITDATA(x) : \
 							  PointerGetDatum(_SGITDATA(x))) \
-							 : (Datum) 0)
+							 : DummyDatum)
 #define SGITNODEPTR(x)		((SpGistNodeTuple) (_SGITDATA(x) + (x)->prefixSize))
 
 /* Macro for iterating through the nodes of an inner tuple */
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h
index 6240ec930e7..10a57039630 100644
--- a/src/include/access/tupmacs.h
+++ b/src/include/access/tupmacs.h
@@ -68,7 +68,7 @@ fetch_att(const void *T, bool attbyval, int attlen)
 #endif
 			default:
 				elog(ERROR, "unsupported byval length: %d", attlen);
-				return 0;
+				return DummyDatum;
 		}
 	}
 	else
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 104b059544d..c529b29c521 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -416,7 +416,7 @@ ExecEvalExprNoReturn(ExprState *state,
 
 	retDatum = state->evalfunc(state, econtext, NULL);
 
-	Assert(retDatum == (Datum) 0);
+	Assert(retDatum.value == 0);  // XXX
 }
 #endif
 
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 0fe7b4ebc77..a0a2816f1c7 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -343,10 +343,12 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum);
 
 /* To return a NULL do this: */
 #define PG_RETURN_NULL()  \
-	do { fcinfo->isnull = true; return (Datum) 0; } while (0)
+	do { fcinfo->isnull = true; return DummyDatum; } while (0)
+
+#define PG_RETURN_DUMMY()	 return DummyDatum
 
 /* A few internal functions return void (which is not the same as NULL!) */
-#define PG_RETURN_VOID()	 return (Datum) 0
+#define PG_RETURN_VOID()	 PG_RETURN_DUMMY()
 
 /* Macros for returning results of standard types */
 
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fbe333d88fa..a4c1cfddea4 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -188,6 +188,8 @@ castNodeImpl(NodeTag type, void *ptr)
  * ----------------------------------------------------------------
  */
 
+typedef struct Datum Datum;
+
 /*
  * nodes/{outfuncs.c,print.c}
  */
@@ -198,7 +200,7 @@ extern void outNode(struct StringInfoData *str, const void *obj);
 extern void outToken(struct StringInfoData *str, const char *s);
 extern void outBitmapset(struct StringInfoData *str,
 						 const struct Bitmapset *bms);
-extern void outDatum(struct StringInfoData *str, uintptr_t value,
+extern void outDatum(struct StringInfoData *str, Datum value,
 					 int typlen, bool typbyval);
 extern char *nodeToString(const void *obj);
 extern char *nodeToStringWithLocations(const void *obj);
@@ -212,7 +214,7 @@ extern void *stringToNode(const char *str);
 extern void *stringToNodeWithLocations(const char *str);
 #endif
 extern struct Bitmapset *readBitmapset(void);
-extern uintptr_t readDatum(bool typbyval);
+extern Datum readDatum(bool typbyval);
 extern bool *readBoolCols(int numCols);
 extern int *readIntCols(int numCols);
 extern Oid *readOidCols(int numCols);
diff --git a/src/include/port/pg_bswap.h b/src/include/port/pg_bswap.h
index 33648433c63..762d9b4c02f 100644
--- a/src/include/port/pg_bswap.h
+++ b/src/include/port/pg_bswap.h
@@ -148,12 +148,12 @@ pg_bswap64(uint64 x)
  */
 #ifdef SIZEOF_DATUM
 #ifdef WORDS_BIGENDIAN
-#define		DatumBigEndianToNative(x)	(x)
+#define		DatumBigEndianToNative(x)	(x.value)
 #else							/* !WORDS_BIGENDIAN */
 #if SIZEOF_DATUM == 8
-#define		DatumBigEndianToNative(x)	pg_bswap64(x)
+#define		DatumBigEndianToNative(x)	pg_bswap64(x.value)
 #else							/* SIZEOF_DATUM != 8 */
-#define		DatumBigEndianToNative(x)	pg_bswap32(x)
+#define		DatumBigEndianToNative(x)	pg_bswap32(x.value)
 #endif							/* SIZEOF_DATUM == 8 */
 #endif							/* WORDS_BIGENDIAN */
 #endif							/* SIZEOF_DATUM */
diff --git a/src/include/postgres.h b/src/include/postgres.h
index 8a41a668687..4c51a78ae9b 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -65,8 +65,11 @@
  * The functions below and the analogous functions for other types should be used to
  * convert between a Datum and the appropriate C type.
  */
+typedef struct Datum {
+	uintptr_t value;
+} Datum;
 
-typedef uintptr_t Datum;
+#define DummyDatum ((Datum){0})
 
 /*
  * A NullableDatum is used in places where both a Datum and its nullness needs
@@ -94,7 +97,7 @@ typedef struct NullableDatum
 static inline bool
 DatumGetBool(Datum X)
 {
-	return (X != 0);
+	return (X.value != 0);
 }
 
 /*
@@ -106,7 +109,7 @@ DatumGetBool(Datum X)
 static inline Datum
 BoolGetDatum(bool X)
 {
-	return (Datum) (X ? 1 : 0);
+	return (Datum){.value = X ? 1 : 0};
 }
 
 /*
@@ -116,7 +119,7 @@ BoolGetDatum(bool X)
 static inline char
 DatumGetChar(Datum X)
 {
-	return (char) X;
+	return (char) X.value;
 }
 
 /*
@@ -126,7 +129,7 @@ DatumGetChar(Datum X)
 static inline Datum
 CharGetDatum(char X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -136,7 +139,7 @@ CharGetDatum(char X)
 static inline Datum
 Int8GetDatum(int8 X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -146,7 +149,7 @@ Int8GetDatum(int8 X)
 static inline uint8
 DatumGetUInt8(Datum X)
 {
-	return (uint8) X;
+	return (uint8) X.value;
 }
 
 /*
@@ -156,7 +159,7 @@ DatumGetUInt8(Datum X)
 static inline Datum
 UInt8GetDatum(uint8 X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -166,7 +169,7 @@ UInt8GetDatum(uint8 X)
 static inline int16
 DatumGetInt16(Datum X)
 {
-	return (int16) X;
+	return (int16) X.value;
 }
 
 /*
@@ -176,7 +179,7 @@ DatumGetInt16(Datum X)
 static inline Datum
 Int16GetDatum(int16 X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -186,7 +189,7 @@ Int16GetDatum(int16 X)
 static inline uint16
 DatumGetUInt16(Datum X)
 {
-	return (uint16) X;
+	return (uint16) X.value;
 }
 
 /*
@@ -196,7 +199,7 @@ DatumGetUInt16(Datum X)
 static inline Datum
 UInt16GetDatum(uint16 X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -206,7 +209,7 @@ UInt16GetDatum(uint16 X)
 static inline int32
 DatumGetInt32(Datum X)
 {
-	return (int32) X;
+	return (int32) X.value;
 }
 
 /*
@@ -216,7 +219,7 @@ DatumGetInt32(Datum X)
 static inline Datum
 Int32GetDatum(int32 X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -226,7 +229,7 @@ Int32GetDatum(int32 X)
 static inline uint32
 DatumGetUInt32(Datum X)
 {
-	return (uint32) X;
+	return (uint32) X.value;
 }
 
 /*
@@ -236,7 +239,7 @@ DatumGetUInt32(Datum X)
 static inline Datum
 UInt32GetDatum(uint32 X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -246,7 +249,7 @@ UInt32GetDatum(uint32 X)
 static inline Oid
 DatumGetObjectId(Datum X)
 {
-	return (Oid) X;
+	return (Oid) X.value;
 }
 
 /*
@@ -256,7 +259,7 @@ DatumGetObjectId(Datum X)
 static inline Datum
 ObjectIdGetDatum(Oid X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -266,7 +269,7 @@ ObjectIdGetDatum(Oid X)
 static inline TransactionId
 DatumGetTransactionId(Datum X)
 {
-	return (TransactionId) X;
+	return (TransactionId) X.value;
 }
 
 /*
@@ -276,7 +279,7 @@ DatumGetTransactionId(Datum X)
 static inline Datum
 TransactionIdGetDatum(TransactionId X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -286,7 +289,7 @@ TransactionIdGetDatum(TransactionId X)
 static inline Datum
 MultiXactIdGetDatum(MultiXactId X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -296,7 +299,7 @@ MultiXactIdGetDatum(MultiXactId X)
 static inline CommandId
 DatumGetCommandId(Datum X)
 {
-	return (CommandId) X;
+	return (CommandId) X.value;
 }
 
 /*
@@ -306,7 +309,7 @@ DatumGetCommandId(Datum X)
 static inline Datum
 CommandIdGetDatum(CommandId X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 
 /*
@@ -316,7 +319,7 @@ CommandIdGetDatum(CommandId X)
 static inline Pointer
 DatumGetPointer(Datum X)
 {
-	return (Pointer) X;
+	return (Pointer) X.value;
 }
 
 /*
@@ -326,7 +329,7 @@ DatumGetPointer(Datum X)
 static inline Datum
 PointerGetDatum(const void *X)
 {
-	return (Datum) X;
+	return (Datum){.value = (uintptr_t) X};
 }
 
 /*
@@ -390,7 +393,7 @@ static inline int64
 DatumGetInt64(Datum X)
 {
 #ifdef USE_FLOAT8_BYVAL
-	return (int64) X;
+	return (int64) X.value;
 #else
 	return *((int64 *) DatumGetPointer(X));
 #endif
@@ -407,7 +410,7 @@ DatumGetInt64(Datum X)
 static inline Datum
 Int64GetDatum(int64 X)
 {
-	return (Datum) X;
+	return (Datum){.value = X};
 }
 #else
 extern Datum Int64GetDatum(int64 X);
@@ -424,7 +427,7 @@ static inline uint64
 DatumGetUInt64(Datum X)
 {
 #ifdef USE_FLOAT8_BYVAL
-	return (uint64) X;
+	return (uint64) X.value;
 #else
 	return *((uint64 *) DatumGetPointer(X));
 #endif
@@ -441,7 +444,7 @@ static inline Datum
 UInt64GetDatum(uint64 X)
 {
 #ifdef USE_FLOAT8_BYVAL
-	return (Datum) X;
+	return (Datum){.value = X};
 #else
 	return Int64GetDatum((int64) X);
 #endif
diff --git a/src/include/utils/arrayaccess.h b/src/include/utils/arrayaccess.h
index 0e48ee07f57..d43837931ed 100644
--- a/src/include/utils/arrayaccess.h
+++ b/src/include/utils/arrayaccess.h
@@ -93,7 +93,7 @@ array_iter_next(array_iter *it, bool *isnull, int i,
 		if (it->bitmapptr && (*(it->bitmapptr) & it->bitmask) == 0)
 		{
 			*isnull = true;
-			ret = (Datum) 0;
+			ret = DummyDatum;
 		}
 		else
 		{
diff --git a/src/include/utils/sortsupport.h b/src/include/utils/sortsupport.h
index b7abaf7802d..699c7c5d675 100644
--- a/src/include/utils/sortsupport.h
+++ b/src/include/utils/sortsupport.h
@@ -254,7 +254,7 @@ ApplyUnsignedSortComparator(Datum datum1, bool isNull1,
 	}
 	else
 	{
-		compare = datum1 < datum2 ? -1 : datum1 > datum2 ? 1 : 0;
+		compare = datum1.value < datum2.value ? -1 : datum1.value > datum2.value ? 1 : 0;
 		if (ssup->ssup_reverse)
 			INVERT_COMPARE_RESULT(compare);
 	}
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 3039713259e..4b9633a2e7a 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -89,45 +89,45 @@ extern bool RelationSupportsSysCache(Oid relid);
  * maximum number of keys.
  */
 #define SearchSysCacheCopy1(cacheId, key1) \
-	SearchSysCacheCopy(cacheId, key1, 0, 0, 0)
+	SearchSysCacheCopy(cacheId, key1, DummyDatum, DummyDatum, DummyDatum)
 #define SearchSysCacheCopy2(cacheId, key1, key2) \
-	SearchSysCacheCopy(cacheId, key1, key2, 0, 0)
+	SearchSysCacheCopy(cacheId, key1, key2, DummyDatum, DummyDatum)
 #define SearchSysCacheCopy3(cacheId, key1, key2, key3) \
-	SearchSysCacheCopy(cacheId, key1, key2, key3, 0)
+	SearchSysCacheCopy(cacheId, key1, key2, key3, DummyDatum)
 #define SearchSysCacheCopy4(cacheId, key1, key2, key3, key4) \
 	SearchSysCacheCopy(cacheId, key1, key2, key3, key4)
 
 #define SearchSysCacheExists1(cacheId, key1) \
-	SearchSysCacheExists(cacheId, key1, 0, 0, 0)
+	SearchSysCacheExists(cacheId, key1, DummyDatum, DummyDatum, DummyDatum)
 #define SearchSysCacheExists2(cacheId, key1, key2) \
-	SearchSysCacheExists(cacheId, key1, key2, 0, 0)
+	SearchSysCacheExists(cacheId, key1, key2, DummyDatum, DummyDatum)
 #define SearchSysCacheExists3(cacheId, key1, key2, key3) \
-	SearchSysCacheExists(cacheId, key1, key2, key3, 0)
+	SearchSysCacheExists(cacheId, key1, key2, key3, DummyDatum)
 #define SearchSysCacheExists4(cacheId, key1, key2, key3, key4) \
 	SearchSysCacheExists(cacheId, key1, key2, key3, key4)
 
 #define GetSysCacheOid1(cacheId, oidcol, key1) \
-	GetSysCacheOid(cacheId, oidcol, key1, 0, 0, 0)
+	GetSysCacheOid(cacheId, oidcol, key1, DummyDatum, DummyDatum, DummyDatum)
 #define GetSysCacheOid2(cacheId, oidcol, key1, key2) \
-	GetSysCacheOid(cacheId, oidcol, key1, key2, 0, 0)
+	GetSysCacheOid(cacheId, oidcol, key1, key2, DummyDatum, DummyDatum)
 #define GetSysCacheOid3(cacheId, oidcol, key1, key2, key3) \
-	GetSysCacheOid(cacheId, oidcol, key1, key2, key3, 0)
+	GetSysCacheOid(cacheId, oidcol, key1, key2, key3, DummyDatum)
 #define GetSysCacheOid4(cacheId, oidcol, key1, key2, key3, key4) \
 	GetSysCacheOid(cacheId, oidcol, key1, key2, key3, key4)
 
 #define GetSysCacheHashValue1(cacheId, key1) \
-	GetSysCacheHashValue(cacheId, key1, 0, 0, 0)
+	GetSysCacheHashValue(cacheId, key1, DummyDatum, DummyDatum, DummyDatum)
 #define GetSysCacheHashValue2(cacheId, key1, key2) \
-	GetSysCacheHashValue(cacheId, key1, key2, 0, 0)
+	GetSysCacheHashValue(cacheId, key1, key2, DummyDatum, DummyDatum)
 #define GetSysCacheHashValue3(cacheId, key1, key2, key3) \
-	GetSysCacheHashValue(cacheId, key1, key2, key3, 0)
+	GetSysCacheHashValue(cacheId, key1, key2, key3, DummyDatum)
 #define GetSysCacheHashValue4(cacheId, key1, key2, key3, key4) \
 	GetSysCacheHashValue(cacheId, key1, key2, key3, key4)
 
 #define SearchSysCacheList1(cacheId, key1) \
-	SearchSysCacheList(cacheId, 1, key1, 0, 0)
+	SearchSysCacheList(cacheId, 1, key1, DummyDatum, DummyDatum)
 #define SearchSysCacheList2(cacheId, key1, key2) \
-	SearchSysCacheList(cacheId, 2, key1, key2, 0)
+	SearchSysCacheList(cacheId, 2, key1, key2, DummyDatum)
 #define SearchSysCacheList3(cacheId, key1, key2, key3) \
 	SearchSysCacheList(cacheId, 3, key1, key2, key3)
 
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 73ba1748fe0..e46bda3c108 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -617,7 +617,7 @@ select_perl_context(bool trusted)
 			plperl_untrusted_init();
 
 		/* successfully initialized, so arrange for cleanup */
-		on_proc_exit(plperl_fini, 0);
+		on_proc_exit(plperl_fini, DummyDatum);
 	}
 	else
 	{
@@ -1853,7 +1853,7 @@ PG_FUNCTION_INFO_V1(plperl_call_handler);
 Datum
 plperl_call_handler(PG_FUNCTION_ARGS)
 {
-	Datum		retval = (Datum) 0;
+	Datum		retval = DummyDatum;
 	plperl_call_data *volatile save_call_data = current_call_data;
 	plperl_interp_desc *volatile oldinterp = plperl_active_interp;
 	plperl_call_data this_call_data;
@@ -1870,7 +1870,7 @@ plperl_call_handler(PG_FUNCTION_ARGS)
 		else if (CALLED_AS_EVENT_TRIGGER(fcinfo))
 		{
 			plperl_event_trigger_handler(fcinfo);
-			retval = (Datum) 0;
+			retval = DummyDatum;
 		}
 		else
 			retval = plperl_func_handler(fcinfo);
@@ -2405,7 +2405,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
 	bool		nonatomic;
 	plperl_proc_desc *prodesc;
 	SV		   *perlret;
-	Datum		retval = 0;
+	Datum		retval = DummyDatum;
 	ReturnSetInfo *rsi;
 	ErrorContextCallback pl_error_context;
 
@@ -2492,7 +2492,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
 			rsi->setResult = current_call_data->tuple_store;
 			rsi->setDesc = current_call_data->ret_tdesc;
 		}
-		retval = (Datum) 0;
+		retval = DummyDatum;
 	}
 	else if (prodesc->result_oid)
 	{
@@ -2577,7 +2577,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
 		else if (TRIGGER_FIRED_BY_TRUNCATE(trigdata->tg_event))
 			retval = PointerGetDatum(trigdata->tg_trigtuple);
 		else
-			retval = (Datum) 0; /* can this happen? */
+			retval = DummyDatum; /* can this happen? */
 	}
 	else
 	{
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index ee961425a5b..795072114b1 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1770,7 +1770,7 @@ plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
 				/* other fields are left as 0, might be changed by caller */
 
 				/* preset to NULL */
-				var->value = 0;
+				var->value = DummyDatum;
 				var->isnull = true;
 				var->freeval = false;
 
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index d19425b7a71..39095da2cd0 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -675,7 +675,7 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
 			rsi->setDesc = CreateTupleDescCopy(estate.tuple_store_desc);
 			MemoryContextSwitchTo(oldcxt);
 		}
-		estate.retval = (Datum) 0;
+		estate.retval = DummyDatum;
 		fcinfo->isnull = true;
 	}
 	else if (!estate.retisnull)
@@ -1016,7 +1016,7 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
 				if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED)
 					expanded_record_set_field_internal(rec_new->erh,
 													   i + 1,
-													   (Datum) 0,
+													   DummyDatum,
 													   true,	/* isnull */
 													   false, false);
 		}
@@ -1512,7 +1512,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
 			}
 			else
 			{
-				assign_simple_var(estate, var, (Datum) 0, true, false);
+				assign_simple_var(estate, var, DummyDatum, true, false);
 			}
 			break;
 
@@ -1697,7 +1697,7 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 					 * Free any old value, in case re-entering block, and
 					 * initialize to NULL
 					 */
-					assign_simple_var(estate, var, (Datum) 0, true, false);
+					assign_simple_var(estate, var, DummyDatum, true, false);
 
 					if (var->default_val == NULL)
 					{
@@ -1710,7 +1710,7 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
 						if (var->datatype->typtype == TYPTYPE_DOMAIN)
 							exec_assign_value(estate,
 											  (PLpgSQL_datum *) var,
-											  (Datum) 0,
+											  DummyDatum,
 											  true,
 											  UNKNOWNOID,
 											  -1);
@@ -2611,7 +2611,7 @@ exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
 
 			/* We can now discard any value we had for the temp variable */
 			if (t_var != NULL)
-				assign_simple_var(estate, t_var, (Datum) 0, true, false);
+				assign_simple_var(estate, t_var, DummyDatum, true, false);
 
 			/* Evaluate the statement(s), and we're done */
 			return exec_stmts(estate, cwt->stmts);
@@ -2620,7 +2620,7 @@ exec_stmt_case(PLpgSQL_execstate *estate, PLpgSQL_stmt_case *stmt)
 
 	/* We can now discard any value we had for the temp variable */
 	if (t_var != NULL)
-		assign_simple_var(estate, t_var, (Datum) 0, true, false);
+		assign_simple_var(estate, t_var, DummyDatum, true, false);
 
 	/* SQL2003 mandates this error if there was no ELSE clause */
 	if (!stmt->have_else)
@@ -2990,7 +2990,7 @@ exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
 	SPI_cursor_close(portal);
 
 	if (curname == NULL)
-		assign_simple_var(estate, curvar, (Datum) 0, true, false);
+		assign_simple_var(estate, curvar, DummyDatum, true, false);
 
 	return rc;
 }
@@ -3205,7 +3205,7 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
 		return PLPGSQL_RC_RETURN;
 
 	/* initialize for null result */
-	estate->retval = (Datum) 0;
+	estate->retval = DummyDatum;
 	estate->retisnull = true;
 	estate->rettype = InvalidOid;
 
@@ -3322,7 +3322,7 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
 	if (estate->fn_rettype == VOIDOID &&
 		estate->func->fn_prokind != PROKIND_PROCEDURE)
 	{
-		estate->retval = (Datum) 0;
+		estate->retval = DummyDatum;
 		estate->retisnull = false;
 		estate->rettype = VOIDOID;
 	}
@@ -4005,7 +4005,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
 	estate->trigdata = NULL;
 	estate->evtrigdata = NULL;
 
-	estate->retval = (Datum) 0;
+	estate->retval = DummyDatum;
 	estate->retisnull = true;
 	estate->rettype = InvalidOid;
 
@@ -5148,7 +5148,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
 				 * promise in any case --- otherwise, assigning null to an
 				 * armed promise variable would fail to disarm the promise.
 				 */
-				if (var->value != newvalue || var->isnull || isNull)
+				if (var->value.value != newvalue.value || var->isnull || isNull)
 					assign_simple_var(estate, var, newvalue, isNull,
 									  (!var->datatype->typbyval && !isNull));
 				else
@@ -5356,7 +5356,7 @@ exec_eval_datum(PLpgSQL_execstate *estate,
 				if (rec->erh == NULL)
 				{
 					/* Treat uninstantiated record as a simple NULL */
-					*value = (Datum) 0;
+					*value = DummyDatum;
 					*isnull = true;
 					/* Report variable's declared type */
 					*typeid = rec->rectypeid;
@@ -5367,7 +5367,7 @@ exec_eval_datum(PLpgSQL_execstate *estate,
 					if (ExpandedRecordIsEmpty(rec->erh))
 					{
 						/* Empty record is also a NULL */
-						*value = (Datum) 0;
+						*value = DummyDatum;
 						*isnull = true;
 					}
 					else
@@ -5682,7 +5682,7 @@ exec_eval_expr(PLpgSQL_execstate *estate,
 			   Oid *rettype,
 			   int32 *rettypmod)
 {
-	Datum		result = 0;
+	Datum		result = DummyDatum;
 	int			rc;
 	Form_pg_attribute attr;
 
@@ -5735,7 +5735,7 @@ exec_eval_expr(PLpgSQL_execstate *estate,
 	if (estate->eval_processed == 0)
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 
 	/*
@@ -6401,7 +6401,7 @@ plpgsql_param_fetch(ParamListInfo params,
 	/* Return "no such parameter" if not ok */
 	if (!ok)
 	{
-		prm->value = (Datum) 0;
+		prm->value = DummyDatum;
 		prm->isnull = true;
 		prm->pflags = 0;
 		prm->ptype = InvalidOid;
@@ -6658,7 +6658,7 @@ plpgsql_param_eval_var_transfer(ExprState *state, ExprEvalStep *op,
 											   get_eval_mcontext(estate));
 		*op->resnull = false;
 
-		var->value = (Datum) 0;
+		var->value = DummyDatum;
 		var->isnull = true;
 		var->freeval = false;
 	}
@@ -7293,7 +7293,7 @@ exec_move_row_from_fields(PLpgSQL_execstate *estate,
 				else
 				{
 					/* no source for destination column */
-					value = (Datum) 0;
+					value = DummyDatum;
 					isnull = true;
 					valtype = UNKNOWNOID;
 					valtypmod = -1;
@@ -7402,7 +7402,7 @@ exec_move_row_from_fields(PLpgSQL_execstate *estate,
 			else
 			{
 				/* no source for destination column */
-				value = (Datum) 0;
+				value = DummyDatum;
 				isnull = true;
 				valtype = UNKNOWNOID;
 				valtypmod = -1;
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index e9a72929947..479819d1aa2 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -227,7 +227,7 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
 	PLpgSQL_function *func;
 	PLpgSQL_execstate *save_cur_estate;
 	ResourceOwner procedure_resowner;
-	volatile Datum retval = (Datum) 0;
+	volatile Datum retval = DummyDatum;
 	int			rc;
 
 	nonatomic = fcinfo->context &&
diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index 28fbd443b98..ee130bf0351 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -214,7 +214,7 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
 			}
 
 			fcinfo->isnull = false;
-			rv = (Datum) 0;
+			rv = DummyDatum;
 		}
 		else if (plrv == Py_None &&
 				 srfstate && srfstate->iter == NULL)
@@ -225,7 +225,7 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
 			 * complain.
 			 */
 			fcinfo->isnull = true;
-			rv = (Datum) 0;
+			rv = DummyDatum;
 		}
 		else
 		{
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index f6509a41902..69f3c9ab413 100644
--- a/src/pl/plpython/plpy_typeio.c
+++ b/src/pl/plpython/plpy_typeio.c
@@ -885,7 +885,7 @@ PLyObject_ToBool(PLyObToDatum *arg, PyObject *plrv,
 	if (plrv == Py_None)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	*isnull = false;
 	return BoolGetDatum(PyObject_IsTrue(plrv));
@@ -901,12 +901,12 @@ PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv,
 				  bool *isnull, bool inarray)
 {
 	PyObject   *volatile plrv_so = NULL;
-	Datum		rv = (Datum) 0;
+	Datum		rv = DummyDatum;
 
 	if (plrv == Py_None)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	*isnull = false;
 
@@ -950,7 +950,7 @@ PLyObject_ToComposite(PLyObToDatum *arg, PyObject *plrv,
 	if (plrv == Py_None)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	*isnull = false;
 
@@ -1082,7 +1082,7 @@ PLyObject_ToScalar(PLyObToDatum *arg, PyObject *plrv,
 	if (plrv == Py_None)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	*isnull = false;
 
@@ -1122,7 +1122,7 @@ PLyObject_ToTransform(PLyObToDatum *arg, PyObject *plrv,
 	if (plrv == Py_None)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	*isnull = false;
 	return FunctionCall1(&arg->u.transform.typtransform, PointerGetDatum(plrv));
@@ -1144,7 +1144,7 @@ PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv,
 	if (plrv == Py_None)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return DummyDatum;
 	}
 	*isnull = false;
 
@@ -1364,7 +1364,7 @@ PLyMapping_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *mapping)
 
 		if (attr->attisdropped)
 		{
-			values[i] = (Datum) 0;
+			//values[i] = DummyDatum;
 			nulls[i] = true;
 			continue;
 		}
@@ -1445,7 +1445,7 @@ PLySequence_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *sequence)
 
 		if (TupleDescAttr(desc, i)->attisdropped)
 		{
-			values[i] = (Datum) 0;
+			//values[i] = DummyDatum;
 			nulls[i] = true;
 			continue;
 		}
@@ -1504,7 +1504,7 @@ PLyGenericObject_ToComposite(PLyObToDatum *arg, TupleDesc desc, PyObject *object
 
 		if (attr->attisdropped)
 		{
-			values[i] = (Datum) 0;
+			//values[i] = DummyDatum;
 			nulls[i] = true;
 			continue;
 		}
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 73d660e88a6..de3d4f6a5ab 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -726,7 +726,7 @@ pltclu_call_handler(PG_FUNCTION_ARGS)
 static Datum
 pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted)
 {
-	Datum		retval = (Datum) 0;
+	Datum		retval = DummyDatum;
 	pltcl_call_state current_call_state;
 	pltcl_call_state *save_call_state;
 
@@ -764,7 +764,7 @@ pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted)
 		{
 			/* invoke the event trigger handler */
 			pltcl_event_trigger_handler(fcinfo, &current_call_state, pltrusted);
-			retval = (Datum) 0;
+			retval = DummyDatum;
 		}
 		else
 		{
@@ -978,7 +978,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
 				MemoryContextSwitchTo(oldcxt);
 			}
 		}
-		retval = (Datum) 0;
+		retval = DummyDatum;
 		fcinfo->isnull = true;
 	}
 	else if (fcinfo->isnull)
diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c
index 31138301117..f07bd27c7f5 100644
--- a/src/test/modules/injection_points/injection_points.c
+++ b/src/test/modules/injection_points/injection_points.c
@@ -512,7 +512,7 @@ injection_points_set_local(PG_FUNCTION_ARGS)
 	 * Register a before_shmem_exit callback to remove any injection points
 	 * linked to this process.
 	 */
-	before_shmem_exit(injection_points_cleanup, (Datum) 0);
+	before_shmem_exit(injection_points_cleanup, DummyDatum);
 
 	PG_RETURN_VOID();
 }
@@ -580,7 +580,7 @@ injection_points_list(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	return DummyDatum;
 #undef NUM_INJECTION_POINTS_LIST
 }
 
diff --git a/src/test/modules/injection_points/injection_stats.c b/src/test/modules/injection_points/injection_stats.c
index e3947b23ba5..072aa70ae53 100644
--- a/src/test/modules/injection_points/injection_stats.c
+++ b/src/test/modules/injection_points/injection_stats.c
@@ -212,7 +212,7 @@ PG_FUNCTION_INFO_V1(injection_points_stats_drop);
 Datum
 injection_points_stats_drop(PG_FUNCTION_ARGS)
 {
-	pgstat_drop_matching_entries(match_inj_entries, 0);
+	pgstat_drop_matching_entries(match_inj_entries, DummyDatum);
 
 	PG_RETURN_VOID();
 }
diff --git a/src/test/modules/plsample/plsample.c b/src/test/modules/plsample/plsample.c
index 78802a94f62..e07482e5736 100644
--- a/src/test/modules/plsample/plsample.c
+++ b/src/test/modules/plsample/plsample.c
@@ -38,7 +38,7 @@ static HeapTuple plsample_trigger_handler(PG_FUNCTION_ARGS);
 Datum
 plsample_call_handler(PG_FUNCTION_ARGS)
 {
-	Datum		retval = (Datum) 0;
+	Datum		retval = DummyDatum;
 
 	/*
 	 * Many languages will require cleanup that happens even in the event of
diff --git a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c
index 193669f2bc1..7c3fb040afe 100644
--- a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c
+++ b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c
@@ -327,5 +327,5 @@ get_altertable_subcmdinfo(PG_FUNCTION_ARGS)
 		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	return (Datum) 0;
+	PG_RETURN_DUMMY();
 }
diff --git a/src/test/modules/test_regex/test_regex.c b/src/test/modules/test_regex/test_regex.c
index 2548a0ef7b1..2d3fe51ddae 100644
--- a/src/test/modules/test_regex/test_regex.c
+++ b/src/test/modules/test_regex/test_regex.c
@@ -717,7 +717,7 @@ build_test_match_result(test_regex_ctx *matchctx)
 		}
 		else if (so < 0 || eo < 0)
 		{
-			elems[i] = (Datum) 0;
+			//elems[i] = DummyDatum;
 			nulls[i] = true;
 		}
 		else if (buf)
-- 
2.50.1