Catching missing Datum conversions

Started by Thomas Munroover 6 years ago3 messages
#1Thomas Munro
thomas.munro@gmail.com
1 attachment(s)

Hi,

When reviewing a recent patch, I missed a place where Datum was being
converted to another type implicitly (ie without going though a
DatumGetXXX() macro). Thanks to Jeff for fixing that (commit
b538c90b), but I was curious to see if I could convince my compiler to
tell me about that sort of thing. Here's an experimental hack that
makes Datum a struct (unfortunately defined in two places, but like I
said it's a hack), and then fixes all the resulting compile errors.
The main categories of change are:

1. Many cases of replacing "(Datum) 0" with a new macro "NullDatum"
and adjusting code that compares with 0/NULL, so you can pretty much
ignore that noise. Likewise code that compares datums directly
without apparent knowledge of the expected type.

2. VARDATA etc macros taking a Datum instead of a varlena *. I think
the interface is suppose to be able to take both, so I think you can
pretty much ignore that noise too, I just couldn't immediately think
of a trick that would make that polymorphism work so I added
DatumGetPointer(x) wherever a Datum x was given directly to those
macros.

3. Many cases of object IDs being converted implicitly, for example
in syscache calls. A few cases of implicit use as booleans.

4. Various confusions about the types involved in PG_RETURN_XXX and
PG_GETARGS_XXX macros, and failure to convert values from
Datum-returning functions, or unnecessary conversion of results (eg
makeArrayResult).

I should probably split this into "actionable" (categories 3 and 4)
and "noise and scaffolding" patches.

--
Thomas Munro
https://enterprisedb.com

Attachments:

0001-Experiment-with-strong-Datum-type.patchtext/x-patch; charset=US-ASCII; name=0001-Experiment-with-strong-Datum-type.patchDownload
From 9408bbf6bc8b4efa96bc18dd60cc27887929f2cc Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 20 Jul 2019 10:10:55 +1200
Subject: [PATCH] Experiment with strong Datum type

---
 contrib/spi/moddatetime.c                     |  2 +-
 src/backend/access/brin/brin.c                |  6 +-
 src/backend/access/brin/brin_minmax.c         | 14 ++--
 src/backend/access/common/heaptuple.c         |  8 +-
 src/backend/access/common/indextuple.c        |  2 +-
 src/backend/access/common/reloptions.c        | 10 +--
 src/backend/access/common/tupconvert.c        |  6 +-
 src/backend/access/common/tupdesc.c           |  6 +-
 src/backend/access/gin/ginscan.c              |  4 +-
 src/backend/access/gin/ginutil.c              |  4 +-
 src/backend/access/gist/gistproc.c            |  6 +-
 src/backend/access/gist/gistutil.c            | 16 ++--
 src/backend/access/heap/tuptoaster.c          |  4 +-
 src/backend/access/index/indexam.c            |  2 +-
 src/backend/access/nbtree/nbtsearch.c         |  2 +-
 src/backend/access/nbtree/nbtutils.c          |  2 +-
 src/backend/access/spgist/spgdoinsert.c       |  8 +-
 src/backend/access/spgist/spgscan.c           | 10 +--
 src/backend/access/spgist/spgutils.c          |  4 +-
 src/backend/access/transam/parallel.c         |  2 +-
 src/backend/access/transam/twophase.c         |  4 +-
 src/backend/access/transam/xlogfuncs.c        |  8 +-
 src/backend/bootstrap/bootparse.y             |  2 +-
 src/backend/bootstrap/bootstrap.c             |  2 +-
 src/backend/catalog/aclchk.c                  | 20 ++---
 src/backend/catalog/catalog.c                 |  2 +-
 src/backend/catalog/heap.c                    | 22 +++---
 src/backend/catalog/index.c                   | 14 ++--
 src/backend/catalog/namespace.c               |  4 +-
 src/backend/catalog/objectaddress.c           |  6 +-
 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                 | 20 ++---
 src/backend/catalog/pg_subscription.c         |  3 +-
 src/backend/catalog/pg_type.c                 |  4 +-
 src/backend/catalog/toasting.c                |  4 +-
 src/backend/commands/alter.c                  |  4 +-
 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          |  6 +-
 src/backend/commands/extension.c              | 10 +--
 src/backend/commands/functioncmds.c           |  4 +-
 src/backend/commands/indexcmds.c              |  2 +-
 src/backend/commands/operatorcmds.c           |  6 +-
 src/backend/commands/prepare.c                |  2 +-
 src/backend/commands/sequence.c               |  4 +-
 src/backend/commands/subscriptioncmds.c       |  9 ++-
 src/backend/commands/tablecmds.c              | 30 ++++----
 src/backend/commands/tablespace.c             |  8 +-
 src/backend/commands/tsearchcmds.c            | 10 +--
 src/backend/commands/typecmds.c               |  2 +-
 src/backend/commands/user.c                   |  2 +-
 src/backend/executor/execExprInterp.c         | 22 +++---
 src/backend/executor/execJunk.c               |  2 +-
 src/backend/executor/execPartition.c          |  2 +-
 src/backend/executor/execSRF.c                |  6 +-
 src/backend/executor/execTuples.c             |  8 +-
 src/backend/executor/execUtils.c              | 15 ++--
 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          | 14 ++--
 src/backend/executor/spi.c                    |  2 +-
 src/backend/foreign/foreign.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/preptlist.c        |  6 +-
 src/backend/optimizer/util/predtest.c         |  2 +-
 src/backend/parser/parse_node.c               |  2 +-
 src/backend/parser/parse_oper.c               |  4 +-
 src/backend/partitioning/partbounds.c         |  6 +-
 src/backend/partitioning/partdesc.c           |  2 +-
 src/backend/port/posix_sema.c                 |  2 +-
 src/backend/port/sysv_shmem.c                 |  2 +-
 src/backend/postmaster/autovacuum.c           |  2 +-
 src/backend/postmaster/checkpointer.c         |  2 +-
 src/backend/postmaster/pgstat.c               |  4 +-
 src/backend/postmaster/postmaster.c           |  4 +-
 src/backend/replication/basebackup.c          |  4 +-
 src/backend/replication/logical/launcher.c    |  8 +-
 .../replication/logical/logicalfuncs.c        |  2 +-
 src/backend/replication/logical/origin.c      |  4 +-
 src/backend/replication/logical/proto.c       |  2 +-
 src/backend/replication/logical/relation.c    |  2 +-
 src/backend/replication/logical/worker.c      |  8 +-
 src/backend/replication/pgoutput/pgoutput.c   |  6 +-
 src/backend/replication/slotfuncs.c           |  4 +-
 src/backend/replication/walreceiver.c         |  2 +-
 src/backend/replication/walsender.c           |  4 +-
 src/backend/rewrite/rewriteDefine.c           |  5 +-
 src/backend/rewrite/rewriteHandler.c          |  4 +-
 src/backend/statistics/mcv.c                  | 10 +--
 src/backend/storage/buffer/bufmgr.c           |  6 +-
 src/backend/storage/file/fd.c                 |  2 +-
 src/backend/storage/file/sharedfileset.c      |  3 +-
 src/backend/storage/ipc/dsm.c                 |  2 +-
 src/backend/storage/ipc/ipc.c                 |  2 +-
 src/backend/storage/lmgr/lock.c               |  8 +-
 src/backend/storage/lmgr/predicate.c          |  2 +-
 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_parse.c                |  4 +-
 src/backend/tsearch/ts_selfuncs.c             |  2 +-
 src/backend/tsearch/ts_typanalyze.c           |  2 +-
 src/backend/tsearch/wparser.c                 | 14 ++--
 src/backend/utils/adt/acl.c                   |  6 +-
 src/backend/utils/adt/amutils.c               |  2 +-
 src/backend/utils/adt/array_selfuncs.c        |  2 +-
 src/backend/utils/adt/array_typanalyze.c      |  2 +-
 src/backend/utils/adt/array_userfuncs.c       | 12 +--
 src/backend/utils/adt/arrayfuncs.c            | 28 +++----
 src/backend/utils/adt/datum.c                 | 10 +--
 src/backend/utils/adt/expandedrecord.c        |  8 +-
 src/backend/utils/adt/json.c                  |  4 +-
 src/backend/utils/adt/jsonb.c                 |  4 +-
 src/backend/utils/adt/jsonb_gin.c             |  6 +-
 src/backend/utils/adt/jsonb_op.c              |  8 +-
 src/backend/utils/adt/jsonfuncs.c             | 40 +++++-----
 src/backend/utils/adt/lockfuncs.c             | 10 +--
 src/backend/utils/adt/mac.c                   | 10 +--
 src/backend/utils/adt/network_gist.c          |  2 +-
 src/backend/utils/adt/numeric.c               | 10 +--
 src/backend/utils/adt/orderedsetaggs.c        | 26 +++----
 src/backend/utils/adt/pgstatfuncs.c           |  8 +-
 src/backend/utils/adt/rangetypes.c            | 42 +++++-----
 src/backend/utils/adt/rangetypes_spgist.c     |  6 +-
 src/backend/utils/adt/regexp.c                |  4 +-
 src/backend/utils/adt/ri_triggers.c           |  2 +-
 src/backend/utils/adt/rowtypes.c              | 12 +--
 src/backend/utils/adt/ruleutils.c             |  2 +-
 src/backend/utils/adt/selfuncs.c              |  6 +-
 src/backend/utils/adt/tid.c                   |  2 +-
 src/backend/utils/adt/tsgistidx.c             |  4 +-
 src/backend/utils/adt/tsquery_op.c            |  2 +-
 src/backend/utils/adt/tsvector_op.c           | 28 +++----
 src/backend/utils/adt/uuid.c                  | 10 +--
 src/backend/utils/adt/varlena.c               | 33 ++++----
 src/backend/utils/adt/xml.c                   | 26 +++----
 src/backend/utils/cache/attoptcache.c         |  2 +-
 src/backend/utils/cache/catcache.c            | 18 ++---
 src/backend/utils/cache/evtcache.c            |  2 +-
 src/backend/utils/cache/lsyscache.c           |  4 +-
 src/backend/utils/cache/partcache.c           |  2 +-
 src/backend/utils/cache/plancache.c           | 16 ++--
 src/backend/utils/cache/relfilenodemap.c      |  2 +-
 src/backend/utils/cache/spccache.c            |  2 +-
 src/backend/utils/cache/syscache.c            |  4 +-
 src/backend/utils/cache/typcache.c            | 10 +--
 src/backend/utils/fmgr/fmgr.c                 |  4 +-
 src/backend/utils/fmgr/funcapi.c              | 11 ++-
 src/backend/utils/init/miscinit.c             |  2 +-
 src/backend/utils/init/postinit.c             |  4 +-
 src/backend/utils/misc/guc.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         | 22 +++---
 src/backend/utils/sort/sortsupport.c          |  2 +-
 src/backend/utils/sort/tuplesort.c            |  4 +-
 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/fmgr.h                            |  4 +-
 src/include/nodes/nodes.h                     |  4 +-
 src/include/postgres.h                        | 77 +++++++++++--------
 src/include/postgres_ext.h                    |  9 +++
 src/include/utils/arrayaccess.h               |  2 +-
 src/include/utils/jsonpath.h                  |  4 +-
 src/include/utils/syscache.h                  | 28 +++----
 src/pl/plpgsql/src/pl_comp.c                  |  2 +-
 src/pl/plpgsql/src/pl_exec.c                  | 38 ++++-----
 src/pl/plpgsql/src/pl_handler.c               |  2 +-
 src/test/regress/regress.c                    |  8 +-
 187 files changed, 690 insertions(+), 661 deletions(-)

diff --git a/contrib/spi/moddatetime.c b/contrib/spi/moddatetime.c
index 70476f77c2..2a86d5fb16 100644
--- a/contrib/spi/moddatetime.c
+++ b/contrib/spi/moddatetime.c
@@ -115,7 +115,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 = NullDatum;		/* keep compiler quiet */
 	}
 	newdtnull = false;
 
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index ae7b729edd..4004c42355 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -256,7 +256,7 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
 									   PointerGetDatum(bdesc),
 									   PointerGetDatum(bval),
 									   values[keyno],
-									   nulls[keyno]);
+									   BoolGetDatum(nulls[keyno]));
 			/* if that returned true, we need to insert the updated tuple */
 			need_insert |= DatumGetBool(result);
 		}
@@ -651,7 +651,7 @@ brinbuildCallback(Relation index,
 						  attr->attcollation,
 						  PointerGetDatum(state->bs_bdesc),
 						  PointerGetDatum(col),
-						  values[i], isnull[i]);
+						  values[i], BoolGetDatum(isnull[i]));
 	}
 }
 
@@ -1053,7 +1053,7 @@ brin_build_desc(Relation rel)
 		opcInfoFn = index_getprocinfo(rel, keyno + 1, BRIN_PROCNUM_OPCINFO);
 
 		opcinfo[keyno] = (BrinOpcInfo *)
-			DatumGetPointer(FunctionCall1(opcInfoFn, attr->atttypid));
+			DatumGetPointer(FunctionCall1(opcInfoFn, ObjectIdGetDatum(attr->atttypid)));
 		totalstored += opcinfo[keyno]->oi_nstored;
 	}
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index ad0d18ed39..84a3ed2e1d 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -68,7 +68,7 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
 	Datum		newval = PG_GETARG_DATUM(2);
-	bool		isnull = PG_GETARG_DATUM(3);
+	bool		isnull = PG_GETARG_BOOL(3);
 	Oid			colloid = PG_GET_COLLATION();
 	FmgrInfo   *cmpFn;
 	Datum		compar;
@@ -226,7 +226,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			matches = 0;
+			matches = Int32GetDatum(0);
 			break;
 	}
 
@@ -281,8 +281,9 @@ brin_minmax_union(PG_FUNCTION_ARGS)
 	/* Adjust minimum, if B's min is less than A's min */
 	finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
 										 BTLessStrategyNumber);
-	needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[0],
-								 col_a->bv_values[0]);
+	needsadj = DatumGetBool(FunctionCall2Coll(finfo, colloid,
+											  col_b->bv_values[0],
+											  col_a->bv_values[0]));
 	if (needsadj)
 	{
 		if (!attr->attbyval)
@@ -294,8 +295,9 @@ brin_minmax_union(PG_FUNCTION_ARGS)
 	/* Adjust maximum, if B's max is greater than A's max */
 	finfo = minmax_get_strategy_procinfo(bdesc, attno, attr->atttypid,
 										 BTGreaterStrategyNumber);
-	needsadj = FunctionCall2Coll(finfo, colloid, col_b->bv_values[1],
-								 col_a->bv_values[1]);
+	needsadj = DatumGetBool(FunctionCall2Coll(finfo, colloid,
+											  col_b->bv_values[1],
+											  col_a->bv_values[1]));
 	if (needsadj)
 	{
 		if (!attr->attbyval)
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index a48a6cd757..db57951583 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -661,7 +661,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 = NullDatum;
 			break;
 	}
 	return result;
@@ -805,7 +805,7 @@ expand_tuple(HeapTuple *targetHeapTuple,
 
 				targetDataLen = att_addlength_pointer(targetDataLen,
 													  att->attlen,
-													  attrmiss[attnum].am_value);
+													  DatumGetPointer(attrmiss[attnum].am_value));
 			}
 			else
 			{
@@ -944,7 +944,7 @@ expand_tuple(HeapTuple *targetHeapTuple,
 					 &bitMask,
 					 &targetData,
 					 infoMask,
-					 (Datum) 0,
+					 NullDatum,
 					 true);
 		}
 	}							/* end loop over missing attributes */
@@ -1278,7 +1278,7 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
 
 		if (hasnulls && att_isnull(attnum, bp))
 		{
-			values[attnum] = (Datum) 0;
+			values[attnum] = NullDatum;
 			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 cb23be859d..0938c6ae91 100644
--- a/src/backend/access/common/indextuple.c
+++ b/src/backend/access/common/indextuple.c
@@ -449,7 +449,7 @@ index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor,
 
 		if (hasnulls && att_isnull(attnum, bp))
 		{
-			values[attnum] = (Datum) 0;
+			values[attnum] = NullDatum;
 			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 5773021499..6e8c5339f0 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -808,8 +808,8 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
 
 		for (i = 0; i < noldoptions; i++)
 		{
-			char	   *text_str = VARDATA(oldoptions[i]);
-			int			text_len = VARSIZE(oldoptions[i]) - VARHDRSZ;
+			char	   *text_str = VARDATA(DatumGetPointer(oldoptions[i]));
+			int			text_len = VARSIZE(DatumGetPointer(oldoptions[i])) - VARHDRSZ;
 
 			/* Search for a match in defList */
 			foreach(cell, defList)
@@ -946,7 +946,7 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
 	if (astate)
 		result = makeArrayResult(astate, CurrentMemoryContext);
 	else
-		result = (Datum) 0;
+		result = NullDatum;
 
 	return result;
 }
@@ -1115,8 +1115,8 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
 
 		for (i = 0; i < noptions; i++)
 		{
-			char	   *text_str = VARDATA(optiondatums[i]);
-			int			text_len = VARSIZE(optiondatums[i]) - VARHDRSZ;
+			char	   *text_str = VARDATA(DatumGetPointer(optiondatums[i]));
+			int			text_len = VARSIZE(DatumGetPointer(optiondatums[i])) - VARHDRSZ;
 			int			j;
 
 			/* Search for a match in reloptions */
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 8cda16431c..a594716d4d 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -188,7 +188,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] = NullDatum;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
 	return map;
@@ -230,7 +230,7 @@ convert_tuples_by_name(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] = NullDatum;	/* set up the NULL entry */
 	map->inisnull[0] = true;
 
 	return map;
@@ -462,7 +462,7 @@ execute_attr_map_slot(AttrNumber *attrMap,
 		/* attrMap[i] == 0 means it's a NULL datum. */
 		if (j == -1)
 		{
-			outvalues[i] = (Datum) 0;
+			outvalues[i] = NullDatum;
 			outisnull[i] = true;
 		}
 		else
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 6bc4e4c036..23b6622946 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -576,10 +576,10 @@ hashTupleDesc(TupleDesc desc)
 	uint32		s;
 	int			i;
 
-	s = hash_combine(0, hash_uint32(desc->natts));
-	s = hash_combine(s, hash_uint32(desc->tdtypeid));
+	s = hash_combine(0, DatumGetUInt32(hash_uint32(desc->natts)));
+	s = hash_combine(s, DatumGetUInt32(hash_uint32(desc->tdtypeid)));
 	for (i = 0; i < desc->natts; ++i)
-		s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
+		s = hash_combine(s, DatumGetUInt32(hash_uint32(TupleDescAttr(desc, i)->atttypid)));
 
 	return s;
 }
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 74d9821ac1..5ca2c75346 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -188,7 +188,7 @@ ginFillScanKey(GinScanOpaque so, OffsetNumber attnum,
 		else
 		{
 			/* set up hidden entry */
-			queryKey = (Datum) 0;
+			queryKey = NullDatum;
 			switch (searchMode)
 			{
 				case GIN_SEARCH_MODE_INCLUDE_EMPTY:
@@ -382,7 +382,7 @@ ginNewScanKey(IndexScanDesc scan)
 		hasNullQuery = true;
 		ginFillScanKey(so, FirstOffsetNumber,
 					   InvalidStrategy, GIN_SEARCH_MODE_EVERYTHING,
-					   (Datum) 0, 0,
+					   NullDatum, 0,
 					   NULL, NULL, NULL, NULL);
 	}
 
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index cf9699ad18..e6d051fd8c 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -497,7 +497,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	{
 		*nentries = 1;
 		entries = (Datum *) palloc(sizeof(Datum));
-		entries[0] = (Datum) 0;
+		entries[0] = NullDatum;
 		*categories = (GinNullCategory *) palloc(sizeof(GinNullCategory));
 		(*categories)[0] = GIN_CAT_NULL_ITEM;
 		return entries;
@@ -519,7 +519,7 @@ ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
 	{
 		*nentries = 1;
 		entries = (Datum *) palloc(sizeof(Datum));
-		entries[0] = (Datum) 0;
+		entries[0] = NullDatum;
 		*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 118dd9653f..5b02c8cac1 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -1382,7 +1382,8 @@ gist_point_consistent(PG_FUNCTION_ARGS)
 														  PointerGetDatum(entry),
 														  PolygonPGetDatum(query),
 														  Int16GetDatum(RTOverlapStrategyNumber),
-														  0, PointerGetDatum(recheck)));
+														  ObjectIdGetDatum(InvalidOid),
+														  PointerGetDatum(recheck)));
 
 				if (GIST_LEAF(entry) && result)
 				{
@@ -1411,7 +1412,8 @@ gist_point_consistent(PG_FUNCTION_ARGS)
 														  PointerGetDatum(entry),
 														  CirclePGetDatum(query),
 														  Int16GetDatum(RTOverlapStrategyNumber),
-														  0, PointerGetDatum(recheck)));
+														  ObjectIdGetDatum(InvalidOid),
+														  PointerGetDatum(recheck)));
 
 				if (GIST_LEAF(entry) && result)
 				{
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 49df05653b..fedeccf99f 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] = NullDatum;
 			isnull[i] = true;
 		}
 		else
@@ -249,7 +249,7 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno,
 	if (isnull1 && isnull2)
 	{
 		*dstisnull = true;
-		*dst = (Datum) 0;
+		*dst = NullDatum;
 	}
 	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, NullDatum, r, pg, o, l);
 }
 
 IndexTuple
@@ -585,7 +585,7 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 	for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
 	{
 		if (isnull[i])
-			compatt[i] = (Datum) 0;
+			compatt[i] = NullDatum;
 		else
 		{
 			GISTENTRY	centry;
@@ -613,7 +613,7 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 		for (; i < r->rd_att->natts; i++)
 		{
 			if (isnull[i])
-				compatt[i] = (Datum) 0;
+				compatt[i] = NullDatum;
 			else
 				compatt[i] = attdata[i];
 		}
@@ -674,7 +674,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] = NullDatum;
 		}
 		else if (giststate->compressFn[i].fn_oid == InvalidOid)
 		{
@@ -685,7 +685,7 @@ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple)
 			if (!isnull[i])
 				fetchatt[i] = datum;
 			else
-				fetchatt[i] = (Datum) 0;
+				fetchatt[i] = NullDatum;
 		}
 		else
 		{
@@ -695,7 +695,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] = NullDatum;
 		}
 	}
 
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 55d6e91d1c..a1afb39564 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -509,7 +509,7 @@ toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative)
 
 			if (toast_isnull[i])
 				continue;
-			else if (VARATT_IS_EXTERNAL_ONDISK(PointerGetDatum(value)))
+			else if (VARATT_IS_EXTERNAL_ONDISK(DatumGetPointer(value)))
 				toast_delete_datum(rel, value, is_speculative);
 		}
 	}
@@ -1484,7 +1484,7 @@ toast_save_datum(Relation rel, Datum value,
 	int			num_indexes;
 	int			validIndex;
 
-	Assert(!VARATT_IS_EXTERNAL(value));
+	Assert(!VARATT_IS_EXTERNAL(DatumGetPointer(value)));
 
 	/*
 	 * Open the toast relation and its indexes.  We can use the index to check
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 28edd4aca7..3170d61ff2 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -859,7 +859,7 @@ index_store_float8_orderby_distances(IndexScanDesc scan, Oid *orderByTypes,
 
 		for (i = 0; i < scan->numberOfOrderBys; i++)
 		{
-			scan->xs_orderbyvals[i] = (Datum) 0;
+			scan->xs_orderbyvals[i] = NullDatum;
 			scan->xs_orderbynulls[i] = true;
 		}
 
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index c655dadb96..1df5dacd4a 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -899,7 +899,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 										   InvalidOid,
 										   InvalidOid,
 										   InvalidOid,
-										   (Datum) 0);
+										   NullDatum);
 				}
 
 				/*
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 93fab264ae..4253627cc4 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -136,7 +136,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 			arg = index_getattr(itup, i + 1, itupdesc, &null);
 		else
 		{
-			arg = (Datum) 0;
+			arg = NullDatum;
 			null = true;
 		}
 		flags = (null ? SK_ISNULL : 0) | (indoption[i] << SK_BT_INDOPTION_SHIFT);
diff --git a/src/backend/access/spgist/spgdoinsert.c b/src/backend/access/spgist/spgdoinsert.c
index c34c44cd8b..7452f63d48 100644
--- a/src/backend/access/spgist/spgdoinsert.c
+++ b/src/backend/access/spgist/spgdoinsert.c
@@ -861,7 +861,7 @@ doPickSplit(Relation index, SpGistState *state,
 		for (i = 0; i < in.nTuples; i++)
 		{
 			newLeafs[i] = spgFormLeafTuple(state, heapPtrs + i,
-										   (Datum) 0,
+										   NullDatum,
 										   true);
 			totalLeafSizes += newLeafs[i]->size + sizeof(ItemIdData);
 		}
@@ -903,7 +903,7 @@ doPickSplit(Relation index, SpGistState *state,
 	 */
 	for (i = 0; i < out.nNodes; i++)
 	{
-		Datum		label = (Datum) 0;
+		Datum		label = NullDatum;
 		bool		labelisnull = (out.nodeLabels == NULL);
 
 		if (!labelisnull)
@@ -1726,7 +1726,7 @@ spgSplitNodeAction(Relation index, SpGistState *state,
 
 	for (i = 0; i < out->result.splitTuple.prefixNNodes; i++)
 	{
-		Datum		label = (Datum) 0;
+		Datum		label = NullDatum;
 		bool		labelisnull;
 
 		labelisnull = (out->result.splitTuple.prefixNodeLabels == NULL);
@@ -1937,7 +1937,7 @@ spgdoinsert(Relation index, SpGistState *state,
 		}
 	}
 	else
-		leafDatum = (Datum) 0;
+		leafDatum = NullDatum;
 
 	/*
 	 * Compute space needed for a leaf tuple containing the given datum.
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index 557dd18d7e..c6b4e2367a 100644
--- a/src/backend/access/spgist/spgscan.c
+++ b/src/backend/access/spgist/spgscan.c
@@ -129,7 +129,7 @@ spgAddStartItem(SpGistScanOpaque so, bool isnull)
 				   FirstOffsetNumber);
 	startEntry->isLeaf = false;
 	startEntry->level = 0;
-	startEntry->value = (Datum) 0;
+	startEntry->value = NullDatum;
 	startEntry->traversalValue = NULL;
 	startEntry->recheck = false;
 	startEntry->recheckDistances = false;
@@ -416,7 +416,7 @@ spgNewHeapItem(SpGistScanOpaque so, int level, ItemPointer heapPtr,
 	item->level = level;
 	item->heapPtr = *heapPtr;
 	/* copy value to queue cxt out of tmp cxt */
-	item->value = isnull ? (Datum) 0 :
+	item->value = isnull ? NullDatum :
 		datumCopy(leafValue, so->state.attLeafType.attbyval,
 				  so->state.attLeafType.attlen);
 	item->traversalValue = NULL;
@@ -448,7 +448,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 = NullDatum;
 		distances = NULL;
 		recheck = false;
 		recheckDistances = false;
@@ -472,7 +472,7 @@ spgLeafTest(SpGistScanOpaque so, SpGistSearchItem *item,
 		in.returnData = so->want_itup;
 		in.leafDatum = SGLTDATUM(leafTuple, &so->state);
 
-		out.leafValue = (Datum) 0;
+		out.leafValue = NullDatum;
 		out.recheck = false;
 		out.distances = NULL;
 		out.recheckDistances = false;
@@ -562,7 +562,7 @@ spgMakeInnerItem(SpGistScanOpaque so,
 		? datumCopy(out->reconstructedValues[i],
 					so->state.attLeafType.attbyval,
 					so->state.attLeafType.attlen)
-		: (Datum) 0;
+		: NullDatum;
 
 	/*
 	 * Elements of out.traversalValues should be allocated in
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index 45472db147..7693f35b60 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -605,7 +605,7 @@ SpGistGetTypeSize(SpGistTypeDesc *att, Datum datum)
 	else if (att->attlen > 0)
 		size = att->attlen;
 	else
-		size = VARSIZE_ANY(datum);
+		size = VARSIZE_ANY(DatumGetPointer(datum));
 
 	return MAXALIGN(size);
 }
@@ -624,7 +624,7 @@ memcpyDatum(void *target, SpGistTypeDesc *att, Datum datum)
 	}
 	else
 	{
-		size = (att->attlen > 0) ? att->attlen : VARSIZE_ANY(datum);
+		size = (att->attlen > 0) ? att->attlen : VARSIZE_ANY(DatumGetPointer(datum));
 		memcpy(target, DatumGetPointer(datum), size);
 	}
 }
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 55d129a64f..1bb3db7395 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -1270,7 +1270,7 @@ ParallelWorkerMain(Datum main_arg)
 	/* Arrange to signal the leader if we exit. */
 	ParallelMasterPid = fps->parallel_master_pid;
 	ParallelMasterBackendId = fps->parallel_master_backend_id;
-	on_shmem_exit(ParallelWorkerShutdown, (Datum) 0);
+	on_shmem_exit(ParallelWorkerShutdown, Int32GetDatum(0));
 
 	/*
 	 * Now we can find and attach to the error queue provided for us.  That's
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 477709bbc2..319dc8b367 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -392,7 +392,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
 	/* on first call, register the exit hook */
 	if (!twophaseExitRegistered)
 	{
-		before_shmem_exit(AtProcExit_Twophase, 0);
+		before_shmem_exit(AtProcExit_Twophase, NullDatum);
 		twophaseExitRegistered = true;
 	}
 
@@ -563,7 +563,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, NullDatum);
 		twophaseExitRegistered = true;
 	}
 
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index b35043bf71..bf76c88e6f 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -107,7 +107,7 @@ pg_start_backup(PG_FUNCTION_ARGS)
 		startpoint = do_pg_start_backup(backupidstr, fast, NULL, label_file,
 										NULL, tblspc_map_file, false, true);
 
-		before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
+		before_shmem_exit(nonexclusive_base_backup_cleanup, NullDatum);
 	}
 
 	PG_RETURN_LSN(startpoint);
@@ -249,7 +249,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
 		 * and tablespace map so they can be written to disk by the caller.
 		 */
 		stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, NULL);
-		cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
+		cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, NullDatum);
 
 		values[1] = CStringGetTextDatum(label_file->data);
 		values[2] = CStringGetTextDatum(tblspc_map_file->data);
@@ -269,7 +269,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
 	tuplestore_putvalues(tupstore, tupdesc, values, nulls);
 	tuplestore_donestoring(typstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
@@ -625,7 +625,7 @@ pg_wal_lsn_diff(PG_FUNCTION_ARGS)
 								 PG_GETARG_DATUM(0),
 								 PG_GETARG_DATUM(1));
 
-	PG_RETURN_NUMERIC(result);
+	PG_RETURN_DATUM(result);
 }
 
 /*
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 4f2587d74a..756438ccdc 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -253,7 +253,7 @@ Boot_CreateStmt:
 													  shared_relation,
 													  mapped_relation,
 													  ONCOMMIT_NOOP,
-													  (Datum) 0,
+													  NullDatum,
 													  false,
 													  true,
 													  false,
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 9238fbe98d..a0feb86ee9 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -418,7 +418,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
 		pgstat_bestart();
 
 		/* register a before-shutdown callback for LWLock cleanup */
-		before_shmem_exit(ShutdownAuxiliaryProcess, 0);
+		before_shmem_exit(ShutdownAuxiliaryProcess, NullDatum);
 	}
 
 	/*
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 291412e305..6eebaedc1d 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -3901,7 +3901,7 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
 				acl = acldefault(OBJECT_TABLE, ownerId);
 				break;
 		}
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -3955,7 +3955,7 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_DATABASE, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -4009,7 +4009,7 @@ pg_proc_aclmask(Oid proc_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_FUNCTION, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -4063,7 +4063,7 @@ pg_language_aclmask(Oid lang_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_LANGUAGE, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -4143,7 +4143,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 = NullDatum;
 	}
 	else
 	{
@@ -4227,7 +4227,7 @@ pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_SCHEMA, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -4283,7 +4283,7 @@ pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_TABLESPACE, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -4345,7 +4345,7 @@ pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_FDW, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -4407,7 +4407,7 @@ pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_FOREIGN_SERVER, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
@@ -4484,7 +4484,7 @@ pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
 	{
 		/* No ACL, so build default ACL */
 		acl = acldefault(OBJECT_TYPE, ownerId);
-		aclDatum = (Datum) 0;
+		aclDatum = NullDatum;
 	}
 	else
 	{
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index a065419cdb..b01d41f1cf 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -542,5 +542,5 @@ pg_nextoid(PG_FUNCTION_ARGS)
 	table_close(rel, RowExclusiveLock);
 	index_close(idx, RowExclusiveLock);
 
-	return newoid;
+	PG_RETURN_OID(newoid);
 }
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 032fab9ac4..c5d8d17ce8 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -890,11 +890,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 (DatumGetPointer(relacl))
 		values[Anum_pg_class_relacl - 1] = relacl;
 	else
 		nulls[Anum_pg_class_relacl - 1] = true;
-	if (reloptions != (Datum) 0)
+	if (DatumGetPointer(reloptions))
 		values[Anum_pg_class_reloptions - 1] = reloptions;
 	else
 		nulls[Anum_pg_class_reloptions - 1] = true;
@@ -1657,7 +1657,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
 			valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
 				BoolGetDatum(false);
 			replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
-			valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
+			valuesAtt[Anum_pg_attribute_attmissingval - 1] = NullDatum;
 			nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
 			replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
 
@@ -2152,8 +2152,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
 	attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
 									Anum_pg_attrdef_oid);
 	values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
-	values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
-	values[Anum_pg_attrdef_adnum - 1] = attnum;
+	values[Anum_pg_attrdef_adrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
+	values[Anum_pg_attrdef_adnum - 1] = ObjectIdGetDatum(attnum);
 	values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
 
 	tuple = heap_form_tuple(adrel->rd_att, values, nulls);
@@ -2194,13 +2194,13 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
 		Datum		valuesAtt[Natts_pg_attribute];
 		bool		nullsAtt[Natts_pg_attribute];
 		bool		replacesAtt[Natts_pg_attribute];
-		Datum		missingval = (Datum) 0;
+		Datum		missingval = NullDatum;
 		bool		missingIsNull = true;
 
 		MemSet(valuesAtt, 0, sizeof(valuesAtt));
 		MemSet(nullsAtt, false, sizeof(nullsAtt));
 		MemSet(replacesAtt, false, sizeof(replacesAtt));
-		valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
+		valuesAtt[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(true);
 		replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
 
 		if (add_column_mode && !attgenerated)
@@ -2220,7 +2220,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
 			if (missingIsNull)
 			{
 				/* if the default evaluates to NULL, just store a NULL array */
-				missingval = (Datum) 0;
+				missingval = NullDatum;
 			}
 			else
 			{
@@ -2234,7 +2234,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
 															 defAttStruct->attalign));
 			}
 
-			valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
+			valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(!missingIsNull);
 			replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
 			valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
 			replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
@@ -3440,14 +3440,14 @@ StorePartitionKey(Relation rel,
 		pfree(exprString);
 	}
 	else
-		partexprDatum = (Datum) 0;
+		partexprDatum = NullDatum;
 
 	pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
 
 	MemSet(nulls, false, sizeof(nulls));
 
 	/* Only this can ever be NULL */
-	if (!partexprDatum)
+	if (!DatumGetBool(partexprDatum))
 		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 9234e93261..9b27171603 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -574,7 +574,7 @@ UpdateIndexRelation(Oid indexoid,
 		pfree(exprsString);
 	}
 	else
-		exprsDatum = (Datum) 0;
+		exprsDatum = NullDatum;
 
 	/*
 	 * Convert the index predicate (if any) to a text datum.  Note we convert
@@ -589,7 +589,7 @@ UpdateIndexRelation(Oid indexoid,
 		pfree(predString);
 	}
 	else
-		predDatum = (Datum) 0;
+		predDatum = NullDatum;
 
 	/*
 	 * open the system catalog index relation
@@ -620,10 +620,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 (!DatumGetPointer(exprsDatum))
 		nulls[Anum_pg_index_indexprs - 1] = true;
 	values[Anum_pg_index_indpred - 1] = predDatum;
-	if (predDatum == (Datum) 0)
+	if (!DatumGetPointer(predDatum))
 		nulls[Anum_pg_index_indpred - 1] = true;
 
 	tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls);
@@ -916,7 +916,7 @@ index_create(Relation heapRelation,
 	 */
 	InsertPgClassTuple(pg_class, indexRelation,
 					   RelationGetRelid(indexRelation),
-					   (Datum) 0,
+					   NullDatum,
 					   reloptions);
 
 	/* done with pg_class */
@@ -1229,7 +1229,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char
 	indcoloptions = (int2vector *) DatumGetPointer(colOptionDatum);
 
 	/* Fetch options of index if any */
-	classTuple = SearchSysCache1(RELOID, oldIndexId);
+	classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(oldIndexId));
 	if (!HeapTupleIsValid(classTuple))
 		elog(ERROR, "cache lookup failed for relation %u", oldIndexId);
 	optionDatum = SysCacheGetAttr(RELOID, classTuple,
@@ -1508,7 +1508,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
 		ScanKeyData skey[3];
 		SysScanDesc sd;
 		HeapTuple	tuple;
-		Datum		values[Natts_pg_description] = {0};
+		Datum		values[Natts_pg_description] = {NullDatum};
 		bool		nulls[Natts_pg_description] = {0};
 		bool		replaces[Natts_pg_description] = {0};
 
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 5cdd51cb5d..ed59ee77b1 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -4000,7 +4000,7 @@ AtEOXact_Namespace(bool isCommit, bool parallel)
 	if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
 	{
 		if (isCommit)
-			before_shmem_exit(RemoveTempRelationsCallback, 0);
+			before_shmem_exit(RemoveTempRelationsCallback, NullDatum);
 		else
 		{
 			myTempNamespace = InvalidOid;
@@ -4260,7 +4260,7 @@ InitializeSearchPath(void)
 		 */
 		CacheRegisterSyscacheCallback(NAMESPACEOID,
 									  NamespaceCallback,
-									  (Datum) 0);
+									  NullDatum);
 		/* Force search path to be recomputed on next use */
 		baseSearchPathValid = false;
 	}
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index caf48cefa9..ac8f5b7507 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -3852,8 +3852,10 @@ pg_identify_object(PG_FUNCTION_ARGS)
 			nspAttnum = get_object_attnum_namespace(address.classId);
 			if (nspAttnum != InvalidAttrNumber)
 			{
-				schema_oid = heap_getattr(objtup, nspAttnum,
-										  RelationGetDescr(catalog), &isnull);
+				schema_oid =
+					DatumGetObjectId(heap_getattr(objtup, nspAttnum,
+												  RelationGetDescr(catalog),
+												  &isnull));
 				if (isnull)
 					elog(ERROR, "invalid null namespace in object %u/%u/%d",
 						 address.classId, address.objectId, address.objectSubId);
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 7cab039ded..f1a6097879 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -650,7 +650,7 @@ AggregateCreate(const char *aggName,
 	for (i = 0; i < Natts_pg_aggregate; i++)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;
+		values[i] = NullDatum;
 		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 b6145593a3..e913e0c19d 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -161,7 +161,7 @@ CreateConstraintEntry(const char *constraintName,
 	for (i = 0; i < Natts_pg_constraint; i++)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;
+		values[i] = NullDatum;
 	}
 
 	conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
index 04c207662a..e51aaecc73 100644
--- a/src/backend/catalog/pg_conversion.c
+++ b/src/backend/catalog/pg_conversion.c
@@ -90,7 +90,7 @@ ConversionCreate(const char *conname, Oid connamespace,
 	for (i = 0; i < Natts_pg_conversion; i++)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) NULL;
+		values[i] = NullDatum;
 	}
 
 	/* form a tuple */
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index 81958813b1..7ff914506b 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] = NullDatum;
 	}
 
 	nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId,
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index bcaa26c997..41e3e09ceb 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -231,7 +231,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] = NullDatum;		/* redundant, but safe */
 	}
 
 	/*
@@ -485,7 +485,7 @@ OperatorCreate(const char *operatorName,
 
 	for (i = 0; i < Natts_pg_operator; ++i)
 	{
-		values[i] = (Datum) NULL;
+		values[i] = NullDatum;
 		replaces[i] = true;
 		nulls[i] = false;
 	}
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index ef009ad2bc..5ab1501e3a 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -135,7 +135,7 @@ ProcedureCreate(const char *procedureName,
 	/* note: the above is correct, we do NOT count output arguments */
 
 	/* Deconstruct array inputs */
-	if (allParameterTypes != PointerGetDatum(NULL))
+	if (DatumGetPointer(allParameterTypes))
 	{
 		/*
 		 * We expect the array to be a 1-D OID array; verify that. We don't
@@ -160,7 +160,7 @@ ProcedureCreate(const char *procedureName,
 		allParams = parameterTypes->values;
 	}
 
-	if (parameterModes != PointerGetDatum(NULL))
+	if (DatumGetPointer(parameterModes))
 	{
 		/*
 		 * We expect the array to be a 1-D CHAR array; verify that. We don't
@@ -201,7 +201,7 @@ ProcedureCreate(const char *procedureName,
 		}
 	}
 
-	if (allParameterTypes != PointerGetDatum(NULL))
+	if (DatumGetPointer(allParameterTypes))
 	{
 		for (i = 0; i < allParamCount; i++)
 		{
@@ -308,7 +308,7 @@ ProcedureCreate(const char *procedureName,
 	for (i = 0; i < Natts_pg_proc; ++i)
 	{
 		nulls[i] = false;
-		values[i] = (Datum) 0;
+		values[i] = NullDatum;
 		replaces[i] = true;
 	}
 
@@ -332,15 +332,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 (DatumGetPointer(allParameterTypes))
 		values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
 	else
 		nulls[Anum_pg_proc_proallargtypes - 1] = true;
-	if (parameterModes != PointerGetDatum(NULL))
+	if (DatumGetPointer(parameterModes))
 		values[Anum_pg_proc_proargmodes - 1] = parameterModes;
 	else
 		nulls[Anum_pg_proc_proargmodes - 1] = true;
-	if (parameterNames != PointerGetDatum(NULL))
+	if (DatumGetPointer(parameterNames))
 		values[Anum_pg_proc_proargnames - 1] = parameterNames;
 	else
 		nulls[Anum_pg_proc_proargnames - 1] = true;
@@ -348,7 +348,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 (DatumGetPointer(trftypes))
 		values[Anum_pg_proc_protrftypes - 1] = trftypes;
 	else
 		nulls[Anum_pg_proc_protrftypes - 1] = true;
@@ -357,7 +357,7 @@ ProcedureCreate(const char *procedureName,
 		values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
 	else
 		nulls[Anum_pg_proc_probin - 1] = true;
-	if (proconfig != PointerGetDatum(NULL))
+	if (DatumGetPointer(proconfig))
 		values[Anum_pg_proc_proconfig - 1] = proconfig;
 	else
 		nulls[Anum_pg_proc_proconfig - 1] = true;
@@ -1169,6 +1169,6 @@ oid_array_to_list(Datum datum)
 					  sizeof(Oid), true, 'i',
 					  &values, NULL, &nelems);
 	for (i = 0; i < nelems; i++)
-		result = lappend_oid(result, values[i]);
+		result = lappend_oid(result, DatumGetObjectId(values[i]));
 	return result;
 }
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index afee2838cc..61dac2243a 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -170,7 +170,8 @@ get_subscription_oid(const char *subname, bool missing_ok)
 	Oid			oid;
 
 	oid = GetSysCacheOid2(SUBSCRIPTIONNAME, Anum_pg_subscription_oid,
-						  MyDatabaseId, CStringGetDatum(subname));
+						  ObjectIdGetDatum(MyDatabaseId),
+						  CStringGetDatum(subname));
 	if (!OidIsValid(oid) && !missing_ok)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 2a51501d8d..78225771ec 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -79,7 +79,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] = NullDatum;		/* redundant, but safe */
 	}
 
 	/*
@@ -337,7 +337,7 @@ TypeCreate(Oid newTypeOid,
 	{
 		nulls[i] = false;
 		replaces[i] = true;
-		values[i] = (Datum) 0;
+		values[i] = NullDatum;
 	}
 
 	/*
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index de6282a667..0d15ce3476 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -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, NullDatum,
 							AccessExclusiveLock, false))
 		elog(ERROR, "\"%s\" does not require a toast table",
 			 relName);
@@ -328,7 +328,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 				 list_make2("chunk_id", "chunk_seq"),
 				 BTREE_AM_OID,
 				 rel->rd_rel->reltablespace,
-				 collationObjectId, classObjectId, coloptions, (Datum) 0,
+				 collationObjectId, classObjectId, coloptions, NullDatum,
 				 INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL);
 
 	table_close(toast_rel, NoLock);
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 70dbcb0756..90acfb4ffd 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -223,7 +223,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
 		Assert(!isnull);
 		ownerId = DatumGetObjectId(datum);
 
-		if (!has_privs_of_role(GetUserId(), DatumGetObjectId(ownerId)))
+		if (!has_privs_of_role(GetUserId(), ownerId))
 			aclcheck_error(ACLCHECK_NOT_OWNER, objtype, old_name);
 
 		/* User must have CREATE privilege on the namespace */
@@ -271,7 +271,7 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
 	}
 	else if (classId == SubscriptionRelationId)
 	{
-		if (SearchSysCacheExists2(SUBSCRIPTIONNAME, MyDatabaseId,
+		if (SearchSysCacheExists2(SUBSCRIPTIONNAME, ObjectIdGetDatum(MyDatabaseId),
 								  CStringGetDatum(new_name)))
 			report_name_conflict(classId, new_name);
 
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 8d633f2585..d7174849f9 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -794,7 +794,7 @@ compute_index_stats(Relation onerel, double totalrows,
 
 					if (isnull[attnum - 1])
 					{
-						exprvals[tcnt] = (Datum) 0;
+						exprvals[tcnt] = NullDatum;
 						exprnulls[tcnt] = true;
 					}
 					else
@@ -1486,7 +1486,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 			else
 			{
 				nulls[i] = true;
-				values[i++] = (Datum) 0;
+				values[i++] = NullDatum;
 			}
 		}
 		i = Anum_pg_statistic_stavalues1 - 1;
@@ -1507,7 +1507,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 			else
 			{
 				nulls[i] = true;
-				values[i++] = (Datum) 0;
+				values[i++] = NullDatum;
 			}
 		}
 
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 6e9c580ec6..fbe62ca148 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -925,7 +925,7 @@ Exec_ListenPreCommit(void)
 	 */
 	if (!unlistenExitRegistered)
 	{
-		before_shmem_exit(Async_UnlistenOnExit, 0);
+		before_shmem_exit(Async_UnlistenOnExit, NullDatum);
 		unlistenExitRegistered = true;
 	}
 
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index cedb4ee844..1ea7fdad1b 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -670,7 +670,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, char relpersistence,
 	reloptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
 								 &isNull);
 	if (isNull)
-		reloptions = (Datum) 0;
+		reloptions = NullDatum;
 
 	if (relpersistence == RELPERSISTENCE_TEMP)
 		namespaceid = LookupCreationNamespace("pg_temp");
@@ -743,7 +743,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, char relpersistence,
 		reloptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
 									 &isNull);
 		if (isNull)
-			reloptions = (Datum) 0;
+			reloptions = NullDatum;
 
 		NewHeapCreateToastTable(OIDNewHeap, reloptions, lockmode);
 
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index b7d220699f..e17bd7c7df 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -125,7 +125,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(NullDatum,
 										create->options,
 										"toast",
 										validnsps,
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index efef120c03..72300e7025 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -1564,7 +1564,7 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
@@ -2121,8 +2121,8 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 								elog(ERROR, "cache lookup failed for object %u/%u",
 									 addr.classId, addr.objectId);
 							schema_oid =
-								heap_getattr(objtup, nspAttnum,
-											 RelationGetDescr(catalog), &isnull);
+								DatumGetObjectId(heap_getattr(objtup, nspAttnum,
+												 RelationGetDescr(catalog), &isnull));
 							if (isnull)
 								elog(ERROR,
 									 "invalid null namespace in object %u/%u/%d",
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index f7202cc9e7..d4202acb66 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1796,12 +1796,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 (!DatumGetPointer(extConfig))
 		nulls[Anum_pg_extension_extconfig - 1] = true;
 	else
 		values[Anum_pg_extension_extconfig - 1] = extConfig;
 
-	if (extCondition == PointerGetDatum(NULL))
+	if (!DatumGetPointer(extCondition))
 		nulls[Anum_pg_extension_extcondition - 1] = true;
 	else
 		values[Anum_pg_extension_extcondition - 1] = extCondition;
@@ -2002,7 +2002,7 @@ pg_available_extensions(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
@@ -2094,7 +2094,7 @@ pg_available_extension_versions(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
@@ -2338,7 +2338,7 @@ pg_extension_update_paths(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 40f1f9a1b6..2b56e174c6 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -449,7 +449,7 @@ interpret_function_parameter_list(ParseState *pstate,
 	{
 		for (i = 0; i < parameterCount; i++)
 		{
-			if (paramNames[i] == PointerGetDatum(NULL))
+			if (!DatumGetPointer(paramNames[i]))
 				paramNames[i] = CStringGetTextDatum("");
 		}
 		*parameterNames = construct_array(paramNames, parameterCount, TEXTOID,
@@ -1372,7 +1372,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] = NullDatum;
 			repl_null[Anum_pg_proc_proconfig - 1] = true;
 		}
 		else
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index fd299273c5..0566547ec8 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -773,7 +773,7 @@ DefineIndex(Oid relationId,
 	/*
 	 * Parse AM-specific options, convert to text array form, validate.
 	 */
-	reloptions = transformRelOptions((Datum) 0, stmt->options,
+	reloptions = transformRelOptions(NullDatum, stmt->options,
 									 NULL, NULL, false, false);
 
 	(void) index_reloptions(amoptions, reloptions, true);
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 17f54410a0..51341667eb 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -500,19 +500,19 @@ AlterOperator(AlterOperatorStmt *stmt)
 	/* Update the tuple */
 	for (i = 0; i < Natts_pg_operator; ++i)
 	{
-		values[i] = (Datum) 0;
+		values[i] = NullDatum;
 		replaces[i] = false;
 		nulls[i] = false;
 	}
 	if (updateRestriction)
 	{
 		replaces[Anum_pg_operator_oprrest - 1] = true;
-		values[Anum_pg_operator_oprrest - 1] = restrictionOid;
+		values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionOid);
 	}
 	if (updateJoin)
 	{
 		replaces[Anum_pg_operator_oprjoin - 1] = true;
-		values[Anum_pg_operator_oprjoin - 1] = joinOid;
+		values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinOid);
 	}
 
 	tup = heap_modify_tuple(tup, RelationGetDescr(catalog),
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index c12b613763..77368ff75e 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -779,7 +779,7 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 	rsinfo->setResult = tupstore;
 	rsinfo->setDesc = tupdesc;
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 0960b339ca..61a2eaf341 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1757,7 +1757,7 @@ sequence_options(Oid relid)
 	Form_pg_sequence pgsform;
 	List	   *options = NIL;
 
-	pgstuple = SearchSysCache1(SEQRELID, relid);
+	pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
 	if (!HeapTupleIsValid(pgstuple))
 		elog(ERROR, "cache lookup failed for sequence %u", relid);
 	pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
@@ -1820,7 +1820,7 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
 
 	memset(isnull, 0, sizeof(isnull));
 
-	pgstuple = SearchSysCache1(SEQRELID, relid);
+	pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
 	if (!HeapTupleIsValid(pgstuple))
 		elog(ERROR, "cache lookup failed for sequence %u", relid);
 	pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 2e67a5889e..8d8b8436de 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -370,7 +370,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
 
 	/* Check if name is used */
 	subid = GetSysCacheOid2(SUBSCRIPTIONNAME, Anum_pg_subscription_oid,
-							MyDatabaseId, CStringGetDatum(stmt->subname));
+							ObjectIdGetDatum(MyDatabaseId),
+							CStringGetDatum(stmt->subname));
 	if (OidIsValid(subid))
 	{
 		ereport(ERROR,
@@ -648,7 +649,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
 	rel = table_open(SubscriptionRelationId, RowExclusiveLock);
 
 	/* Fetch the existing tuple. */
-	tup = SearchSysCacheCopy2(SUBSCRIPTIONNAME, MyDatabaseId,
+	tup = SearchSysCacheCopy2(SUBSCRIPTIONNAME, ObjectIdGetDatum(MyDatabaseId),
 							  CStringGetDatum(stmt->subname));
 
 	if (!HeapTupleIsValid(tup))
@@ -858,7 +859,7 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
 	 */
 	rel = table_open(SubscriptionRelationId, AccessExclusiveLock);
 
-	tup = SearchSysCache2(SUBSCRIPTIONNAME, MyDatabaseId,
+	tup = SearchSysCache2(SUBSCRIPTIONNAME, ObjectIdGetDatum(MyDatabaseId),
 						  CStringGetDatum(stmt->subname));
 
 	if (!HeapTupleIsValid(tup))
@@ -1089,7 +1090,7 @@ AlterSubscriptionOwner(const char *name, Oid newOwnerId)
 
 	rel = table_open(SubscriptionRelationId, RowExclusiveLock);
 
-	tup = SearchSysCacheCopy2(SUBSCRIPTIONNAME, MyDatabaseId,
+	tup = SearchSysCacheCopy2(SUBSCRIPTIONNAME, ObjectIdGetDatum(MyDatabaseId),
 							  CStringGetDatum(name));
 
 	if (!HeapTupleIsValid(tup))
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index fc1c4dfa4c..4db43638f4 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -716,7 +716,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 	/*
 	 * Parse and validate reloptions, if any.
 	 */
-	reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
+	reloptions = transformRelOptions(NullDatum, stmt->options, NULL, validnsps,
 									 true, false);
 
 	if (relkind == RELKIND_VIEW)
@@ -4209,7 +4209,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, NullDatum, lockmode);
 	}
 }
 
@@ -6827,7 +6827,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 ? NullDatum : datum,
 									 castNode(List, options), NULL, NULL,
 									 false, isReset);
 	/* Validate new options */
@@ -6836,7 +6836,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 (DatumGetPointer(newOptions))
 		repl_val[Anum_pg_attribute_attoptions - 1] = newOptions;
 	else
 		repl_null[Anum_pg_attribute_attoptions - 1] = true;
@@ -8488,7 +8488,7 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel)
 		Oid			conffeqop[INDEX_MAX_KEYS];
 		Constraint *fkconstraint;
 
-		tuple = SearchSysCache1(CONSTROID, constrOid);
+		tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constrOid));
 		if (!HeapTupleIsValid(tuple))
 			elog(ERROR, "cache lookup failed for constraint %u", constrOid);
 		constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
@@ -8633,7 +8633,7 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
 					referenced;
 		ListCell   *cell;
 
-		tuple = SearchSysCache1(CONSTROID, parentConstrOid);
+		tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(parentConstrOid));
 		if (!HeapTupleIsValid(tuple))
 			elog(ERROR, "cache lookup failed for constraint %u",
 				 parentConstrOid);
@@ -11514,7 +11514,7 @@ ATExecAlterColumnGenericOptions(Relation rel,
 
 	/* First, determine FDW validator associated to the foreign table. */
 	ftrel = table_open(ForeignTableRelationId, AccessShareLock);
-	tuple = SearchSysCache1(FOREIGNTABLEREL, rel->rd_id);
+	tuple = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(rel->rd_id));
 	if (!HeapTupleIsValid(tuple))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -12081,7 +12081,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 = NullDatum;
 		isnull = true;
 	}
 	else
@@ -12092,7 +12092,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 	}
 
 	/* Generate new proposed reloptions (text array) */
-	newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
+	newOptions = transformRelOptions(isnull ? NullDatum : datum,
 									 defList, NULL, validnsps, false,
 									 operation == AT_ResetRelOptions);
 
@@ -12161,7 +12161,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 (DatumGetPointer(newOptions))
 		repl_val[Anum_pg_class_reloptions - 1] = newOptions;
 	else
 		repl_null[Anum_pg_class_reloptions - 1] = true;
@@ -12198,7 +12198,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 = NullDatum;
 			isnull = true;
 		}
 		else
@@ -12208,7 +12208,7 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 									&isnull);
 		}
 
-		newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
+		newOptions = transformRelOptions(isnull ? NullDatum : datum,
 										 defList, "toast", validnsps, false,
 										 operation == AT_ResetRelOptions);
 
@@ -12218,7 +12218,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 (DatumGetPointer(newOptions))
 			repl_val[Anum_pg_class_reloptions - 1] = newOptions;
 		else
 			repl_null[Anum_pg_class_reloptions - 1] = true;
@@ -13965,7 +13965,7 @@ ATExecGenericOptions(Relation rel, List *options)
 
 	ftrel = table_open(ForeignTableRelationId, RowExclusiveLock);
 
-	tuple = SearchSysCacheCopy1(FOREIGNTABLEREL, rel->rd_id);
+	tuple = SearchSysCacheCopy1(FOREIGNTABLEREL, ObjectIdGetDatum(rel->rd_id));
 	if (!HeapTupleIsValid(tuple))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -16065,7 +16065,7 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
 	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] = NullDatum;
 	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 84efb414d8..cab8f44403 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -346,11 +346,11 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 	nulls[Anum_pg_tablespace_spcacl - 1] = true;
 
 	/* Generate new proposed spcoptions (text array) */
-	newOptions = transformRelOptions((Datum) 0,
+	newOptions = transformRelOptions(NullDatum,
 									 stmt->options,
 									 NULL, NULL, false, false);
 	(void) tablespace_reloptions(newOptions, true);
-	if (newOptions != (Datum) 0)
+	if (DatumGetPointer(newOptions))
 		values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
 	else
 		nulls[Anum_pg_tablespace_spcoptions - 1] = true;
@@ -1048,7 +1048,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 ? NullDatum : datum,
 									 stmt->options, NULL, NULL, false,
 									 stmt->isReset);
 	(void) tablespace_reloptions(newOptions, true);
@@ -1056,7 +1056,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 (DatumGetPointer(newOptions))
 		repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
 	else
 		repl_null[Anum_pg_tablespace_spcoptions - 1] = true;
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 5d6528f9cf..92c587b95b 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1095,10 +1095,10 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
 			memset(mapvalues, 0, sizeof(mapvalues));
 			memset(mapnulls, false, sizeof(mapnulls));
 
-			mapvalues[Anum_pg_ts_config_map_mapcfg - 1] = cfgOid;
-			mapvalues[Anum_pg_ts_config_map_maptokentype - 1] = cfgmap->maptokentype;
-			mapvalues[Anum_pg_ts_config_map_mapseqno - 1] = cfgmap->mapseqno;
-			mapvalues[Anum_pg_ts_config_map_mapdict - 1] = cfgmap->mapdict;
+			mapvalues[Anum_pg_ts_config_map_mapcfg - 1] = ObjectIdGetDatum(cfgOid);
+			mapvalues[Anum_pg_ts_config_map_maptokentype - 1] = ObjectIdGetDatum(cfgmap->maptokentype);
+			mapvalues[Anum_pg_ts_config_map_mapseqno - 1] = ObjectIdGetDatum(cfgmap->mapseqno);
+			mapvalues[Anum_pg_ts_config_map_mapdict - 1] = ObjectIdGetDatum(cfgmap->mapdict);
 
 			newmaptup = heap_form_tuple(mapRel->rd_att, mapvalues, mapnulls);
 
@@ -1244,7 +1244,7 @@ getTokenTypes(Oid prsId, List *tokennames)
 
 	/* lextype takes one dummy argument */
 	list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
-														 (Datum) 0));
+														 NullDatum));
 
 	i = 0;
 	foreach(tn, tokennames)
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 89887b8fd7..d55738de72 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2212,7 +2212,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
 	checkDomainOwner(tup);
 
 	/* Setup new tuple */
-	MemSet(new_record, (Datum) 0, sizeof(new_record));
+	MemSet(new_record, 0, sizeof(new_record));
 	MemSet(new_record_nulls, false, sizeof(new_record_nulls));
 	MemSet(new_record_repl, false, sizeof(new_record_repl));
 
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index aab5aa855d..c589af0bf4 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -359,7 +359,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
 	}
 	else
 	{
-		validUntil_datum = (Datum) 0;
+		validUntil_datum = NullDatum;
 		validUntil_null = true;
 	}
 
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 66a67c72b2..85506d94cf 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -726,7 +726,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			}
 			else if (*op->d.boolexpr.anynull)
 			{
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = NullDatum;
 				*op->resnull = true;
 			}
 			else
@@ -793,7 +793,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			}
 			else if (*op->d.boolexpr.anynull)
 			{
-				*op->resvalue = (Datum) 0;
+				*op->resvalue = NullDatum;
 				*op->resnull = true;
 			}
 			else
@@ -1183,7 +1183,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 = NullDatum;
 					*op->resnull = true;
 
 					EEO_NEXT();
@@ -2043,7 +2043,7 @@ ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	 */
 	outslot->tts_values[resultnum] =
 		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
-	return 0;
+	return NullDatum;
 }
 
 /* Evaluate outer Var and assign to appropriate column of result tuple */
@@ -2061,7 +2061,7 @@ ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	/* See comments in ExecJustAssignInnerVar */
 	outslot->tts_values[resultnum] =
 		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
-	return 0;
+	return NullDatum;
 }
 
 /* Evaluate scan Var and assign to appropriate column of result tuple */
@@ -2079,7 +2079,7 @@ ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	/* See comments in ExecJustAssignInnerVar */
 	outslot->tts_values[resultnum] =
 		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
-	return 0;
+	return NullDatum;
 }
 
 /* Evaluate CASE_TESTVAL and apply a strict function to it */
@@ -2110,7 +2110,7 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
 		if (args[argno].isnull)
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return NullDatum;
 		}
 	}
 	fcinfo->isnull = false;
@@ -3139,7 +3139,7 @@ ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op)
 	if (*op->resnull)
 	{
 		/* whole array is null, so any element or slice is too */
-		sbsrefstate->prevvalue = (Datum) 0;
+		sbsrefstate->prevvalue = NullDatum;
 		sbsrefstate->prevnull = true;
 	}
 	else if (sbsrefstate->numlower == 0)
@@ -3429,7 +3429,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 = NullDatum;
 			fcinfo->args[1].isnull = true;
 		}
 		else
@@ -3445,7 +3445,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
 		if (fcinfo->args[1].isnull && strictfunc)
 		{
 			fcinfo->isnull = true;
-			thisresult = (Datum) 0;
+			thisresult = NullDatum;
 		}
 		else
 		{
@@ -3536,7 +3536,7 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
 	int			i;
 
 	*op->resnull = true;		/* until we get a result */
-	*op->resvalue = (Datum) 0;
+	*op->resvalue = NullDatum;
 
 	switch (xexpr->op)
 	{
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 897ff52e03..4a2be5d797 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -301,7 +301,7 @@ ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
 
 		if (j == 0)
 		{
-			values[i] = (Datum) 0;
+			values[i] = NullDatum;
 			isnull[i] = true;
 		}
 		else
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index f49a48adb6..1eaa42cadc 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -1472,7 +1472,7 @@ adjust_partition_tlist(List *tlist, TupleConversionMap *map)
 							 -1,
 							 InvalidOid,
 							 sizeof(int32),
-							 (Datum) 0,
+							 NullDatum,
 							 true,	/* isnull */
 							 true /* byval */ );
 			tle = makeTargetEntry((Expr *) expr,
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index c8a3efc365..dc5299550e 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -536,7 +536,7 @@ restart:
 		fcache->funcResultStore = NULL;
 		*isDone = ExprEndResult;
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	/*
@@ -613,7 +613,7 @@ restart:
 	else
 	{
 		/* for a strict SRF, result for NULL is an empty set */
-		result = (Datum) 0;
+		result = NullDatum;
 		*isNull = true;
 		*isDone = ExprEndResult;
 	}
@@ -659,7 +659,7 @@ restart:
 		/* if setResult was left null, treat it as empty set */
 		*isDone = ExprEndResult;
 		*isNull = true;
-		result = (Datum) 0;
+		result = NullDatum;
 	}
 	else
 		ereport(ERROR,
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 5ee2a464bb..3613c6b002 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -137,7 +137,7 @@ tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
 {
 	elog(ERROR, "virtual tuple table slot does not have system attributes");
 
-	return 0;					/* silence compiler warnings */
+	return NullDatum;				/* silence compiler warnings */
 }
 
 /*
@@ -498,7 +498,7 @@ tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
 {
 	elog(ERROR, "minimal tuple table slot does not have system attributes");
 
-	return 0;					/* silence compiler warnings */
+	return NullDatum;					/* silence compiler warnings */
 }
 
 static void
@@ -929,7 +929,7 @@ slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
 
 		if (hasnulls && att_isnull(attnum, bp))
 		{
-			values[attnum] = (Datum) 0;
+			values[attnum] = NullDatum;
 			isnull[attnum] = true;
 			slow = true;		/* can't use attcacheoff anymore */
 			continue;
@@ -2141,7 +2141,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
 		else
 		{
 			/* Handle dropped attributes by setting to NULL */
-			dvalues[i] = (Datum) 0;
+			dvalues[i] = NullDatum;
 			nulls[i] = true;
 		}
 	}
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index c1fc0d54e9..d55e742cb5 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -275,10 +275,10 @@ CreateExprContext(EState *estate)
 	econtext->ecxt_aggvalues = NULL;
 	econtext->ecxt_aggnulls = NULL;
 
-	econtext->caseValue_datum = (Datum) 0;
+	econtext->caseValue_datum = NullDatum;
 	econtext->caseValue_isNull = true;
 
-	econtext->domainValue_datum = (Datum) 0;
+	econtext->domainValue_datum = NullDatum;
 	econtext->domainValue_isNull = true;
 
 	econtext->ecxt_estate = estate;
@@ -344,10 +344,10 @@ CreateStandaloneExprContext(void)
 	econtext->ecxt_aggvalues = NULL;
 	econtext->ecxt_aggnulls = NULL;
 
-	econtext->caseValue_datum = (Datum) 0;
+	econtext->caseValue_datum = NullDatum;
 	econtext->caseValue_isNull = true;
 
-	econtext->domainValue_datum = (Datum) 0;
+	econtext->domainValue_datum = NullDatum;
 	econtext->domainValue_isNull = true;
 
 	econtext->ecxt_estate = NULL;
@@ -912,7 +912,8 @@ 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);
@@ -993,7 +994,7 @@ GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull)
 	{
 		/* Kinda bogus but compatible with old behavior... */
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	tupType = HeapTupleHeaderGetTypeId(tuple);
@@ -1056,7 +1057,7 @@ GetAttributeByNum(HeapTupleHeader tuple,
 	{
 		/* Kinda bogus but compatible with old behavior... */
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	tupType = HeapTupleHeaderGetTypeId(tuple);
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 64a9e58462..69eb714735 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -1257,7 +1257,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 			rsi->isDone = ExprEndResult;
 
 			fcinfo->isnull = true;
-			result = (Datum) 0;
+			result = NullDatum;
 
 			/* Deregister shutdown callback, if we made one */
 			if (fcache->shutdown_reg)
@@ -1283,7 +1283,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 				rsi->setDesc = CreateTupleDescCopy(fcache->junkFilter->jf_cleanTupType);
 
 			fcinfo->isnull = true;
-			result = (Datum) 0;
+			result = NullDatum;
 
 			/* Deregister shutdown callback, if we made one */
 			if (fcache->shutdown_reg)
@@ -1310,7 +1310,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 			else
 			{
 				fcinfo->isnull = true;
-				result = (Datum) 0;
+				result = NullDatum;
 			}
 		}
 		else
@@ -1318,7 +1318,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
 			/* Should only get here for VOID functions and procedures */
 			Assert(fcache->rettype == VOIDOID);
 			fcinfo->isnull = true;
-			result = (Datum) 0;
+			result = NullDatum;
 		}
 
 		/* Clear the tuplestore, but keep it for next time */
@@ -1836,7 +1836,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 												   -1,
 												   InvalidOid,
 												   sizeof(int32),
-												   (Datum) 0,
+												   NullDatum,
 												   true,	/* isnull */
 												   true /* byval */ );
 					newtlist = lappend(newtlist,
@@ -1898,7 +1898,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 											   -1,
 											   InvalidOid,
 											   sizeof(int32),
-											   (Datum) 0,
+											   NullDatum,
 											   true,	/* isnull */
 											   true /* byval */ );
 				newtlist = lappend(newtlist,
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index cb4ab4b21e..38345444fd 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -708,14 +708,14 @@ process_ordered_aggregate_single(AggState *aggstate,
 								 AggStatePerTrans pertrans,
 								 AggStatePerGroup pergroupstate)
 {
-	Datum		oldVal = (Datum) 0;
+	Datum		oldVal = NullDatum;
 	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 = NullDatum;
+	Datum		oldAbbrevVal = NullDatum;
 	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
 	Datum	   *newVal;
 	bool	   *isNull;
@@ -751,7 +751,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)))))
@@ -806,8 +806,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 = NullDatum;
+	Datum		oldAbbrevVal = NullDatum;
 	bool		haveOldValue = false;
 	TupleTableSlot *save = aggstate->tmpcontext->ecxt_outertuple;
 	int			i;
@@ -828,7 +828,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
 
 		if (numDistinctCols == 0 ||
 			!haveOldValue ||
-			newAbbrevVal != oldAbbrevVal ||
+			newAbbrevVal.value != oldAbbrevVal.value ||
 			!ExecQual(pertrans->equalfnMulti, tmpcontext))
 		{
 			/*
@@ -948,7 +948,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 = NullDatum;
 			fcinfo->args[i].isnull = true;
 			anynull = true;
 		}
@@ -956,7 +956,7 @@ finalize_aggregate(AggState *aggstate,
 		if (fcinfo->flinfo->fn_strict && anynull)
 		{
 			/* don't call a strict function with NULL inputs */
-			*resultVal = (Datum) 0;
+			*resultVal = NullDatum;
 			*resultIsNull = true;
 		}
 		else
@@ -1012,7 +1012,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 = NullDatum;
 			*resultIsNull = true;
 		}
 		else
@@ -2761,7 +2761,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 									  Anum_pg_aggregate_agginitval,
 									  &initValueIsNull);
 		if (initValueIsNull)
-			initValue = (Datum) 0;
+			initValue = NullDatum;
 		else
 			initValue = GetAggInitVal(textInitVal, aggtranstype);
 
@@ -3713,5 +3713,5 @@ aggregate_dummy(PG_FUNCTION_ARGS)
 {
 	elog(ERROR, "aggregate function %u called as normal function",
 		 fcinfo->flinfo->fn_oid);
-	return (Datum) 0;			/* keep compiler quiet */
+	return NullDatum;			/* keep compiler quiet */
 }
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 0370f2e2b7..1db4722592 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -197,7 +197,7 @@ FunctionNext(FunctionScanState *node)
 			 */
 			for (i = 0; i < fs->colcount; i++)
 			{
-				scanslot->tts_values[att] = (Datum) 0;
+				scanslot->tts_values[att] = NullDatum;
 				scanslot->tts_isnull[att] = true;
 				att++;
 			}
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index ac7aa81f67..771af9e57b 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -480,7 +480,7 @@ reorderqueue_push(IndexScanState *node, TupleTableSlot *slot,
 										   node->iss_OrderByTypByVals[i],
 										   node->iss_OrderByTypLens[i]);
 		else
-			rt->orderbyvals[i] = (Datum) 0;
+			rt->orderbyvals[i] = NullDatum;
 		rt->orderbynulls[i] = orderbynulls[i];
 	}
 	pairingheap_add(node->iss_ReorderQueue, &rt->ph_node);
@@ -1280,7 +1280,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 				runtime_keys[n_runtime_keys].key_toastable =
 					TypeIsToastable(op_righttype);
 				n_runtime_keys++;
-				scanvalue = (Datum) 0;
+				scanvalue = NullDatum;
 			}
 
 			/*
@@ -1404,7 +1404,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 					runtime_keys[n_runtime_keys].key_toastable =
 						TypeIsToastable(op_righttype);
 					n_runtime_keys++;
-					scanvalue = (Datum) 0;
+					scanvalue = NullDatum;
 				}
 
 				/*
@@ -1528,7 +1528,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 					 */
 					runtime_keys[n_runtime_keys].key_toastable = true;
 					n_runtime_keys++;
-					scanvalue = (Datum) 0;
+					scanvalue = NullDatum;
 				}
 			}
 			else
@@ -1539,7 +1539,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 					ExecInitExpr(rightop, planstate);
 				/* the remaining fields were zeroed by palloc0 */
 				n_array_keys++;
-				scanvalue = (Datum) 0;
+				scanvalue = NullDatum;
 			}
 
 			/*
@@ -1603,7 +1603,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
 								   InvalidOid,	/* no strategy subtype */
 								   InvalidOid,	/* no collation */
 								   InvalidOid,	/* no reg proc for this */
-								   (Datum) 0);	/* constant */
+								   NullDatum);	/* constant */
 		}
 		else
 			elog(ERROR, "unsupported indexqual type: %d",
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index facdb4232e..9408e5b275 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -163,7 +163,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 = NullDatum;
 			*isnull = true;
 			hassrf = true;
 		}
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index f6445e286a..0da4a4c94c 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -259,7 +259,7 @@ ExecScanSubPlan(SubPlanState *node,
 			prm->execPlan = node;
 		}
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	/* Initialize ArrayBuildStateAny in caller's context, if needed */
@@ -456,7 +456,7 @@ ExecScanSubPlan(SubPlanState *node,
 		if (subLinkType == EXPR_SUBLINK ||
 			subLinkType == ROWCOMPARE_SUBLINK)
 		{
-			result = (Datum) 0;
+			result = NullDatum;
 			*isNull = true;
 		}
 	}
@@ -1184,7 +1184,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))
 			pfree(DatumGetPointer(node->curArray));
 		node->curArray = makeArrayResultAny(astate,
 											econtext->ecxt_per_query_memory,
@@ -1214,7 +1214,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 				ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);
 
 				prm->execPlan = NULL;
-				prm->value = (Datum) 0;
+				prm->value = NullDatum;
 				prm->isnull = true;
 			}
 		}
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index def00cd7c5..1e1174566c 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -228,7 +228,7 @@ initialize_windowaggregate(WindowAggState *winstate,
 	}
 	peraggstate->transValueIsNull = peraggstate->initValueIsNull;
 	peraggstate->transValueCount = 0;
-	peraggstate->resultValue = (Datum) 0;
+	peraggstate->resultValue = NullDatum;
 	peraggstate->resultValueIsNull = true;
 }
 
@@ -608,7 +608,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 = NullDatum;
 			fcinfo->args[i].isnull = true;
 			anynull = true;
 		}
@@ -616,7 +616,7 @@ finalize_windowaggregate(WindowAggState *winstate,
 		if (fcinfo->flinfo->fn_strict && anynull)
 		{
 			/* don't call a strict function with NULL inputs */
-			*result = (Datum) 0;
+			*result = NullDatum;
 			*isnull = true;
 		}
 		else
@@ -894,7 +894,7 @@ eval_windowaggregates(WindowAggState *winstate)
 		{
 			if (!peraggstate->resulttypeByVal)
 				pfree(DatumGetPointer(peraggstate->resultValue));
-			peraggstate->resultValue = (Datum) 0;
+			peraggstate->resultValue = NullDatum;
 			peraggstate->resultValueIsNull = true;
 		}
 	}
@@ -2814,7 +2814,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
 								  &peraggstate->initValueIsNull);
 
 	if (peraggstate->initValueIsNull)
-		peraggstate->initValue = (Datum) 0;
+		peraggstate->initValue = NullDatum;
 	else
 		peraggstate->initValue = GetAggInitVal(textInitVal,
 											   aggtranstype);
@@ -3203,7 +3203,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
 		if (isout)
 			*isout = true;
 		*isnull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 	else
 	{
@@ -3429,7 +3429,7 @@ out_of_frame:
 	if (isout)
 		*isout = true;
 	*isnull = true;
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 74f8d89bcb..9b6722ef26 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1034,7 +1034,7 @@ SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
 	{
 		SPI_result = SPI_ERROR_NOATTRIBUTE;
 		*isnull = true;
-		return (Datum) NULL;
+		return NullDatum;
 	}
 
 	return heap_getattr(tuple, fnumber, tupdesc, isnull);
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index c917ec40ff..5645da92a4 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -549,7 +549,7 @@ deflist_to_tuplestore(ReturnSetInfo *rsinfo, List *options)
 		}
 		else
 		{
-			values[1] = (Datum) 0;
+			values[1] = NullDatum;
 			nulls[1] = true;
 		}
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
@@ -574,7 +574,7 @@ pg_options_to_table(PG_FUNCTION_ARGS)
 	deflist_to_tuplestore((ReturnSetInfo *) fcinfo->resultinfo,
 						  untransformRelOptions(array));
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 384887e70d..107681ad1f 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -202,7 +202,7 @@ pq_init(void)
 	DoingCopyOut = false;
 
 	/* set up process-exit hook to close the socket */
-	on_proc_exit(socket_close, 0);
+	on_proc_exit(socket_close, NullDatum);
 
 	/*
 	 * 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 a9bd47d937..ddff5cc184 100644
--- a/src/backend/libpq/pqmq.c
+++ b/src/backend/libpq/pqmq.c
@@ -58,7 +58,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, NullDatum);
 }
 
 /*
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 7085ed2c4c..091b7df2ae 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -343,7 +343,7 @@ makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
 					 consttypmod,
 					 constcollid,
 					 (int) typLen,
-					 (Datum) 0,
+					 NullDatum,
 					 true,
 					 typByVal);
 }
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 6c2626ee62..7785ceeb6c 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -2847,7 +2847,7 @@ readDatum(bool typbyval)
 	{
 		if (length > (Size) sizeof(Datum))
 			elog(ERROR, "byval datum but length = %zu", length);
-		res = (Datum) 0;
+		res = NullDatum;
 		s = (char *) (&res);
 		for (i = 0; i < (Size) sizeof(Datum); i++)
 		{
@@ -2856,7 +2856,7 @@ readDatum(bool typbyval)
 		}
 	}
 	else if (length <= 0)
-		res = (Datum) NULL;
+		res = NullDatum;
 	else
 	{
 		s = (char *) palloc(length);
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 792ae393d9..064b527664 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -327,7 +327,7 @@ expand_targetlist(List *tlist, int command_type,
 													  -1,
 													  attcollation,
 													  att_tup->attlen,
-													  (Datum) 0,
+													  NullDatum,
 													  true, /* isnull */
 													  att_tup->attbyval);
 						new_expr = coerce_to_domain(new_expr,
@@ -345,7 +345,7 @@ expand_targetlist(List *tlist, int command_type,
 													  -1,
 													  InvalidOid,
 													  sizeof(int32),
-													  (Datum) 0,
+													  NullDatum,
 													  true, /* isnull */
 													  true /* byval */ );
 					}
@@ -367,7 +367,7 @@ expand_targetlist(List *tlist, int command_type,
 													  -1,
 													  InvalidOid,
 													  sizeof(int32),
-													  (Datum) 0,
+													  NullDatum,
 													  true, /* isnull */
 													  true /* byval */ );
 					}
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 08a160fff6..995ba71943 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -1991,7 +1991,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);
+									  NullDatum);
 	}
 
 	key.pred_op = pred_op;
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 1baf7ef31f..2d2ed35f57 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -569,7 +569,7 @@ make_const(ParseState *pstate, Value *value, int location)
 							-1,
 							InvalidOid,
 							-2,
-							(Datum) 0,
+							NullDatum,
 							true,
 							false);
 			con->location = location;
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 0e1015962d..7f67d530f4 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -1092,10 +1092,10 @@ find_oper_cache_entry(OprCacheKey *key)
 		/* Arrange to flush cache on pg_operator and pg_cast changes */
 		CacheRegisterSyscacheCallback(OPERNAMENSP,
 									  InvalidateOprCacheCallBack,
-									  (Datum) 0);
+									  NullDatum);
 		CacheRegisterSyscacheCallback(CASTSOURCETARGET,
 									  InvalidateOprCacheCallBack,
-									  (Datum) 0);
+									  NullDatum);
 	}
 
 	/* Look for an existing entry */
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 7d8907b2b4..277b6f410a 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -716,8 +716,8 @@ partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval,
 		 * at b1->datums[i][0] and b1->datums[i][1] position respectively.
 		 */
 		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
@@ -2322,7 +2322,7 @@ get_qual_for_range(Relation parent, PartitionBoundSpec *spec,
 			bool		isnull;
 			PartitionBoundSpec *bspec;
 
-			tuple = SearchSysCache1(RELOID, inhrelid);
+			tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(inhrelid));
 			if (!HeapTupleIsValid(tuple))
 				elog(ERROR, "cache lookup failed for relation %u", inhrelid);
 
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index b207b765f2..795c6b4a7c 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -97,7 +97,7 @@ RelationBuildPartitionDesc(Relation rel)
 		PartitionBoundSpec *boundspec = NULL;
 
 		/* Try fetching the tuple from the catcache, for speed. */
-		tuple = SearchSysCache1(RELOID, inhrelid);
+		tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(inhrelid));
 		if (HeapTupleIsValid(tuple))
 		{
 			Datum		datum;
diff --git a/src/backend/port/posix_sema.c b/src/backend/port/posix_sema.c
index 5e77cb0c12..aee3476af8 100644
--- a/src/backend/port/posix_sema.c
+++ b/src/backend/port/posix_sema.c
@@ -217,7 +217,7 @@ PGReserveSemaphores(int maxSemas, int port)
 	maxSems = maxSemas;
 	nextSemKey = port * 1000;
 
-	on_shmem_exit(ReleaseSemaphores, 0);
+	on_shmem_exit(ReleaseSemaphores, NullDatum);
 }
 
 /*
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 968506dd51..827bfd7ccc 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -648,7 +648,7 @@ PGSharedMemoryCreate(Size size, int port,
 		AnonymousShmemSize = size;
 
 		/* Register on-exit routine to unmap the anonymous segment */
-		on_shmem_exit(AnonymousShmemDetach, (Datum) 0);
+		on_shmem_exit(AnonymousShmemDetach, NullDatum);
 
 		/* Now we need only allocate a minimal-sized SysV shmem block. */
 		sysvsize = sizeof(PGShmemHeader);
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 073f313337..326ef9cdca 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1646,7 +1646,7 @@ AutoVacWorkerMain(int argc, char *argv[])
 		AutoVacuumShmem->av_startingWorker = NULL;
 		LWLockRelease(AutovacuumLock);
 
-		on_shmem_exit(FreeWorkerInfo, 0);
+		on_shmem_exit(FreeWorkerInfo, NullDatum);
 
 		/* wake up the launcher */
 		if (AutoVacuumShmem->av_launcherpid != 0)
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 11bbe2c397..0422458070 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -377,7 +377,7 @@ CheckpointerMain(void)
 			 */
 			ExitOnAnyError = true;
 			/* Close down the database */
-			ShutdownXLOG(0, 0);
+			ShutdownXLOG(0, NullDatum);
 			/* Normal exit from the checkpointer is here */
 			proc_exit(0);		/* done */
 		}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index b4f2b28b51..ac499ed94e 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -1228,7 +1228,7 @@ pgstat_collect_oids(Oid catalogid, AttrNumber anum_oid)
 		Oid			thisoid;
 		bool		isnull;
 
-		thisoid = heap_getattr(tup, anum_oid, RelationGetDescr(rel), &isnull);
+		thisoid = DatumGetObjectId(heap_getattr(tup, anum_oid, RelationGetDescr(rel), &isnull));
 		Assert(!isnull);
 
 		CHECK_FOR_INTERRUPTS();
@@ -2837,7 +2837,7 @@ pgstat_initialize(void)
 	}
 
 	/* Set up a process-exit hook to clean up */
-	on_shmem_exit(pgstat_beshutdown_hook, 0);
+	on_shmem_exit(pgstat_beshutdown_hook, NullDatum);
 }
 
 /* ----------
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 3339804be9..5175c1e2a8 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1006,7 +1006,7 @@ PostmasterMain(int argc, char *argv[])
 	for (i = 0; i < MAXLISTEN; i++)
 		ListenSocket[i] = PGINVALID_SOCKET;
 
-	on_proc_exit(CloseServerPorts, 0);
+	on_proc_exit(CloseServerPorts, NullDatum);
 
 	if (ListenAddresses)
 	{
@@ -1238,7 +1238,7 @@ PostmasterMain(int argc, char *argv[])
 			write_stderr("%s: could not write external PID file \"%s\": %s\n",
 						 progname, external_pid_file, strerror(errno));
 
-		on_proc_exit(unlink_external_pid_file, 0);
+		on_proc_exit(unlink_external_pid_file, NullDatum);
 	}
 
 	/*
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index d5f9b617c8..9b7888fcab 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -254,7 +254,7 @@ perform_base_backup(basebackup_options *opt)
 	 * do_pg_stop_backup() should be inside the error cleanup block!
 	 */
 
-	PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
+	PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, NullDatum);
 	{
 		ListCell   *lc;
 		tablespaceinfo *ti;
@@ -363,7 +363,7 @@ perform_base_backup(basebackup_options *opt)
 
 		endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
 	}
-	PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
+	PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, NullDatum);
 
 
 	if (opt->includewal)
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index 186057bd93..54acd1112f 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -661,7 +661,7 @@ logicalrep_worker_attach(int slot)
 	}
 
 	MyLogicalRepWorker->proc = MyProc;
-	before_shmem_exit(logicalrep_worker_onexit, (Datum) 0);
+	before_shmem_exit(logicalrep_worker_onexit, NullDatum);
 
 	LWLockRelease(LogicalRepWorkerLock);
 }
@@ -805,7 +805,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 = NullDatum;
 
 	RegisterBackgroundWorker(&bgw);
 }
@@ -976,7 +976,7 @@ ApplyLauncherMain(Datum main_arg)
 	ereport(DEBUG1,
 			(errmsg("logical replication launcher started")));
 
-	before_shmem_exit(logicalrep_launcher_onexit, (Datum) 0);
+	before_shmem_exit(logicalrep_launcher_onexit, NullDatum);
 
 	Assert(LogicalRepCtx->launcher_pid == 0);
 	LogicalRepCtx->launcher_pid = MyProcPid;
@@ -1196,5 +1196,5 @@ pg_stat_get_subscription(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index d974400d6e..6e8cc09791 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -364,7 +364,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
 	}
 	PG_END_TRY();
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index 7477ceae28..ce4511962e 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -1062,7 +1062,7 @@ replorigin_session_setup(RepOriginId node)
 
 	if (!registered_cleanup)
 	{
-		on_shmem_exit(ReplicationOriginExitCleanup, 0);
+		on_shmem_exit(ReplicationOriginExitCleanup, NullDatum);
 		registered_cleanup = true;
 	}
 
@@ -1563,5 +1563,5 @@ pg_show_replication_origin_status(PG_FUNCTION_ARGS)
 
 #undef REPLICATION_ORIGIN_PROGRESS_COLS
 
-	return (Datum) 0;
+	return NullDatum;
 }
diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c
index e7df47de3e..0c00141214 100644
--- a/src/backend/replication/logical/proto.c
+++ b/src/backend/replication/logical/proto.c
@@ -481,7 +481,7 @@ logicalrep_write_tuple(StringInfo out, Relation rel, HeapTuple tuple)
 			pq_sendbyte(out, 'n');	/* null column */
 			continue;
 		}
-		else if (att->attlen == -1 && VARATT_IS_EXTERNAL_ONDISK(values[i]))
+		else if (att->attlen == -1 && VARATT_IS_EXTERNAL_ONDISK(DatumGetPointer(values[i])))
 		{
 			pq_sendbyte(out, 'u');	/* unchanged toast column */
 			continue;
diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c
index 85269c037d..8e14718433 100644
--- a/src/backend/replication/logical/relation.c
+++ b/src/backend/replication/logical/relation.c
@@ -112,7 +112,7 @@ logicalrep_relmap_init(void)
 
 	/* Watch for invalidation events. */
 	CacheRegisterRelcacheCallback(logicalrep_relmap_invalidate_cb,
-								  (Datum) 0);
+								  NullDatum);
 }
 
 /*
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 43edfef089..9094769057 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -351,7 +351,7 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 			 * values (missing values should be later filled using
 			 * slot_fill_defaults).
 			 */
-			slot->tts_values[i] = (Datum) 0;
+			slot->tts_values[i] = NullDatum;
 			slot->tts_isnull[i] = true;
 		}
 	}
@@ -420,7 +420,7 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 		}
 		else
 		{
-			slot->tts_values[i] = (Datum) 0;
+			slot->tts_values[i] = NullDatum;
 			slot->tts_isnull[i] = true;
 		}
 	}
@@ -1637,7 +1637,7 @@ ApplyWorkerMain(Datum main_arg)
 	/* Keep us informed about subscription changes. */
 	CacheRegisterSyscacheCallback(SUBSCRIPTIONOID,
 								  subscription_change_cb,
-								  (Datum) 0);
+								  NullDatum);
 
 	if (am_tablesync_worker())
 		ereport(LOG,
@@ -1717,7 +1717,7 @@ ApplyWorkerMain(Datum main_arg)
 	 */
 	CacheRegisterSyscacheCallback(SUBSCRIPTIONRELMAP,
 								  invalidate_syncing_table_states,
-								  (Datum) 0);
+								  NullDatum);
 
 	/* Build logical replication streaming options. */
 	options.logical = true;
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index d317fd7006..876c25047a 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -197,7 +197,7 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 		publications_valid = false;
 		CacheRegisterSyscacheCallback(PUBLICATIONOID,
 									  publication_invalidation_cb,
-									  (Datum) 0);
+									  NullDatum);
 
 		/* Initialize relation schema cache. */
 		init_rel_sync_cache(CacheMemoryContext);
@@ -517,10 +517,10 @@ init_rel_sync_cache(MemoryContext cachectx)
 
 	Assert(RelationSyncCache != NULL);
 
-	CacheRegisterRelcacheCallback(rel_sync_cache_relation_cb, (Datum) 0);
+	CacheRegisterRelcacheCallback(rel_sync_cache_relation_cb, NullDatum);
 	CacheRegisterSyscacheCallback(PUBLICATIONRELMAP,
 								  rel_sync_cache_publication_cb,
-								  (Datum) 0);
+								  NullDatum);
 }
 
 /*
diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
index 808a6f5b83..39401b66a0 100644
--- a/src/backend/replication/slotfuncs.c
+++ b/src/backend/replication/slotfuncs.c
@@ -313,7 +313,7 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
 		if (database == InvalidOid)
 			nulls[i++] = true;
 		else
-			values[i++] = database;
+			values[i++] = ObjectIdGetDatum(database);
 
 		values[i++] = BoolGetDatum(persistency == RS_TEMPORARY);
 		values[i++] = BoolGetDatum(active_pid != 0);
@@ -349,7 +349,7 @@ pg_get_replication_slots(PG_FUNCTION_ARGS)
 
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 6abc780778..33876f2e8a 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -243,7 +243,7 @@ WalReceiverMain(void)
 	SpinLockRelease(&walrcv->mutex);
 
 	/* Arrange to clean up at walreceiver exit */
-	on_shmem_exit(WalRcvDie, 0);
+	on_shmem_exit(WalRcvDie, NullDatum);
 
 	/* Properly accept or ignore signals the postmaster might send us */
 	pqsignal(SIGHUP, WalRcvSigHupHandler);	/* set flag to read config file */
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index e7a59b0a92..15f8ffc1c3 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -2331,7 +2331,7 @@ InitWalSenderSlot(void)
 	Assert(MyWalSnd != NULL);
 
 	/* Arrange to clean up at walsender exit */
-	on_shmem_exit(WalSndKill, 0);
+	on_shmem_exit(WalSndKill, NullDatum);
 }
 
 /* Destroy the per-walsender data structure for this walsender process */
@@ -3394,7 +3394,7 @@ pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 7df2b6154c..e21629643b 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -880,10 +880,9 @@ EnableDisableRule(Relation rel, const char *rulename,
 	/*
 	 * Change ev_enabled if it is different from the desired new state.
 	 */
-	if (DatumGetChar(ruleform->ev_enabled) !=
-		fires_when)
+	if (ruleform->ev_enabled != fires_when)
 	{
-		ruleform->ev_enabled = CharGetDatum(fires_when);
+		ruleform->ev_enabled = fires_when;
 		CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup);
 
 		changed = true;
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 93b6784023..f85ddfef16 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -874,7 +874,7 @@ rewriteTargetListIU(List *targetList,
 												  -1,
 												  att_tup->attcollation,
 												  att_tup->attlen,
-												  (Datum) 0,
+												  NullDatum,
 												  true, /* isnull */
 												  att_tup->attbyval);
 					/* this is to catch a NOT NULL domain constraint */
@@ -1398,7 +1398,7 @@ rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti,
 												  -1,
 												  att_tup->attcollation,
 												  att_tup->attlen,
-												  (Datum) 0,
+												  NullDatum,
 												  true, /* isnull */
 												  att_tup->attbyval);
 					/* this is to catch a NOT NULL domain constraint */
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index e5a4e86c5d..87036d6b8d 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -766,7 +766,7 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
 				values[dim][i] = PointerGetDatum(PG_DETOAST_DATUM(values[dim][i]));
 
 				/* serialized length (uint32 length + data) */
-				len = VARSIZE_ANY_EXHDR(values[dim][i]);
+				len = VARSIZE_ANY_EXHDR(DatumGetPointer(values[dim][i]));
 				info[dim].nbytes += sizeof(uint32);	/* length */
 				info[dim].nbytes += len;			/* value (no header) */
 
@@ -1186,7 +1186,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 = NullDatum;
 
 				memcpy(&v, ptr, info[dim].typlen);
 				ptr += info[dim].typlen;
@@ -1430,15 +1430,15 @@ pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS)
 			}
 			else
 				astate_values = accumArrayResult(astate_values,
-								  (Datum) 0,
+								  NullDatum,
 								  true,
 								  TEXTOID,
 								  CurrentMemoryContext);
 		}
 
 		values[0] = Int32GetDatum(funcctx->call_cntr);
-		values[1] = PointerGetDatum(makeArrayResult(astate_values, CurrentMemoryContext));
-		values[2] = PointerGetDatum(makeArrayResult(astate_nulls, CurrentMemoryContext));
+		values[1] = makeArrayResult(astate_values, CurrentMemoryContext);
+		values[2] = makeArrayResult(astate_nulls, CurrentMemoryContext);
 		values[3] = Float8GetDatum(item->frequency);
 		values[4] = Float8GetDatum(item->base_frequency);
 
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 6f3a402854..11cef9fdba 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2468,7 +2468,7 @@ InitBufferPoolAccess(void)
 void
 InitBufferPoolBackend(void)
 {
-	on_shmem_exit(AtProcExit_Buffers, 0);
+	on_shmem_exit(AtProcExit_Buffers, NullDatum);
 }
 
 /*
@@ -4252,8 +4252,8 @@ ckpt_buforder_comparator(const void *pa, const void *pb)
 static int
 ts_ckpt_progress_comparator(Datum a, Datum b, void *arg)
 {
-	CkptTsStatus *sa = (CkptTsStatus *) a;
-	CkptTsStatus *sb = (CkptTsStatus *) b;
+	CkptTsStatus *sa = (CkptTsStatus *) DatumGetPointer(a);
+	CkptTsStatus *sb = (CkptTsStatus *) DatumGetPointer(b);
 
 	/* we want a min-heap, so return 1 for the a < b */
 	if (sa->progress < sb->progress)
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 315c74c745..32f6d248a6 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -800,7 +800,7 @@ InitFileAccess(void)
 	SizeVfdCache = 1;
 
 	/* register proc-exit hook to ensure temp files are dropped at exit */
-	on_proc_exit(AtProcExit_Files, 0);
+	on_proc_exit(AtProcExit_Files, NullDatum);
 }
 
 /*
diff --git a/src/backend/storage/file/sharedfileset.c b/src/backend/storage/file/sharedfileset.c
index 26e5091172..ee3031d48a 100644
--- a/src/backend/storage/file/sharedfileset.c
+++ b/src/backend/storage/file/sharedfileset.c
@@ -228,7 +228,8 @@ SharedFileSetPath(char *path, SharedFileSet *fileset, Oid tablespace)
 static Oid
 ChooseTablespace(const SharedFileSet *fileset, const char *name)
 {
-	uint32		hash = hash_any((const unsigned char *) name, strlen(name));
+	uint32		hash = DatumGetUInt32(hash_any((const unsigned char *) name,
+											   strlen(name)));
 
 	return fileset->tablespaces[hash % fileset->ntablespaces];
 }
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 142293fd2c..0e937eb636 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -997,7 +997,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/ipc.c b/src/backend/storage/ipc/ipc.c
index 05d02c23f5..b7a0a00038 100644
--- a/src/backend/storage/ipc/ipc.c
+++ b/src/backend/storage/ipc/ipc.c
@@ -392,7 +392,7 @@ 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;
 }
 
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 1b7053cb1c..b437a68db3 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -508,7 +508,6 @@ proclock_hash(const void *key, Size keysize)
 {
 	const PROCLOCKTAG *proclocktag = (const PROCLOCKTAG *) key;
 	uint32		lockhash;
-	Datum		procptr;
 
 	Assert(keysize == sizeof(PROCLOCKTAG));
 
@@ -522,8 +521,7 @@ proclock_hash(const void *key, Size keysize)
 	 * don't care if we lose high-order bits of the address; use an
 	 * intermediate variable to suppress cast-pointer-to-int warnings.
 	 */
-	procptr = PointerGetDatum(proclocktag->myProc);
-	lockhash ^= ((uint32) procptr) << LOG2_NUM_LOCK_PARTITIONS;
+	lockhash ^= ((uint32) proclocktag->myProc) << LOG2_NUM_LOCK_PARTITIONS;
 
 	return lockhash;
 }
@@ -538,13 +536,11 @@ static inline uint32
 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
 {
 	uint32		lockhash = hashcode;
-	Datum		procptr;
 
 	/*
 	 * This must match proclock_hash()!
 	 */
-	procptr = PointerGetDatum(proclocktag->myProc);
-	lockhash ^= ((uint32) procptr) << LOG2_NUM_LOCK_PARTITIONS;
+	lockhash ^= ((uint32) proclocktag->myProc) << LOG2_NUM_LOCK_PARTITIONS;
 
 	return lockhash;
 }
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 2d709420c3..0f5994ef9b 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -312,7 +312,7 @@
  * intermediate variable to suppress cast-pointer-to-int warnings.
  */
 #define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash) \
-	((targethash) ^ ((uint32) PointerGetDatum((predicatelocktag)->myXact)) \
+	((targethash) ^ ((uint32) (predicatelocktag)->myXact) \
 	 << LOG2_NUM_PREDICATELOCK_PARTITIONS)
 
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 498373fd0e..1bdf279ed3 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -460,7 +460,7 @@ InitProcess(void)
 	/*
 	 * Arrange to clean up at backend exit.
 	 */
-	on_shmem_exit(ProcKill, 0);
+	on_shmem_exit(ProcKill, NullDatum);
 
 	/*
 	 * Now that we have a PGPROC, we could try to acquire locks, so initialize
@@ -490,7 +490,7 @@ InitProcessPhase2(void)
 	/*
 	 * Arrange to clean that up at backend exit.
 	 */
-	on_shmem_exit(RemoveProcFromArray, 0);
+	on_shmem_exit(RemoveProcFromArray, NullDatum);
 }
 
 /*
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index b0d9f21e68..e2b5f25f3a 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -118,7 +118,7 @@ smgrinit(void)
 	}
 
 	/* register the shutdown proc */
-	on_proc_exit(smgrshutdown, 0);
+	on_proc_exit(smgrshutdown, NullDatum);
 }
 
 /*
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index 61aa1697c3..0cc926659c 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -368,7 +368,7 @@ HandleFunctionRequest(StringInfo msgBuf)
 	else
 	{
 		fcinfo->isnull = true;
-		retval = (Datum) 0;
+		retval = NullDatum;
 	}
 
 	/* 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 a6505c7335..ca749a9052 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -1853,7 +1853,7 @@ exec_bind_message(StringInfo input_message)
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 						 errmsg("unsupported format code: %d",
 								pformat)));
-				pval = 0;		/* keep compiler quiet */
+				pval = NullDatum;		/* keep compiler quiet */
 			}
 
 			/* Restore message buffer contents */
@@ -3922,7 +3922,7 @@ PostgresMain(int argc, char *argv[],
 	 * sure Log_disconnections has its final value.
 	 */
 	if (IsUnderPostmaster && Log_disconnections)
-		on_proc_exit(log_disconnections, 0);
+		on_proc_exit(log_disconnections, NullDatum);
 
 	/* Perform initialization specific to a WAL sender process. */
 	if (am_walsender)
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 7f6f0b6498..e27ccb0ef9 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1029,7 +1029,7 @@ ProcessUtilitySlow(ParseState *pstate,
 							 * parse and validate reloptions for the toast
 							 * table
 							 */
-							toast_options = transformRelOptions((Datum) 0,
+							toast_options = transformRelOptions(NullDatum,
 																((CreateStmt *) stmt)->options,
 																"toast",
 																validnsps,
diff --git a/src/backend/tsearch/ts_parse.c b/src/backend/tsearch/ts_parse.c
index 171ade273b..920d99aaf3 100644
--- a/src/backend/tsearch/ts_parse.c
+++ b/src/backend/tsearch/ts_parse.c
@@ -219,7 +219,7 @@ LexizeExec(LexizeData *ld, ParsedLex **correspondLexem)
 					 * position and go to multiword mode
 					 */
 
-					ld->curDictId = DatumGetObjectId(map->dictIds[i]);
+					ld->curDictId = map->dictIds[i];
 					ld->posDict = i + 1;
 					ld->curSub = curVal->next;
 					if (res)
@@ -276,7 +276,7 @@ LexizeExec(LexizeData *ld, ParsedLex **correspondLexem)
 				 * dictionaries ?
 				 */
 				for (i = 0; i < map->len && !dictExists; i++)
-					if (ld->curDictId == DatumGetObjectId(map->dictIds[i]))
+					if (ld->curDictId == map->dictIds[i])
 						dictExists = true;
 
 				if (!dictExists)
diff --git a/src/backend/tsearch/ts_selfuncs.c b/src/backend/tsearch/ts_selfuncs.c
index ed935faead..b2e2a594a8 100644
--- a/src/backend/tsearch/ts_selfuncs.c
+++ b/src/backend/tsearch/ts_selfuncs.c
@@ -234,7 +234,7 @@ mcelem_tsquery_selec(TSQuery query, Datum *mcelem, int nmcelem,
 		 * The text Datums came from an array, so it cannot be compressed or
 		 * stored out-of-line -- it's safe to use VARSIZE_ANY*.
 		 */
-		Assert(!VARATT_IS_COMPRESSED(mcelem[i]) && !VARATT_IS_EXTERNAL(mcelem[i]));
+		Assert(!VARATT_IS_COMPRESSED(DatumGetPointer(mcelem[i])) && !VARATT_IS_EXTERNAL(DatumGetPointer(mcelem[i])));
 		lookup[i].element = (text *) DatumGetPointer(mcelem[i]);
 		lookup[i].frequency = numbers[i];
 	}
diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c
index bd33e67e33..4c3b9a31ce 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 a3372a8c84..8682a0eefd 100644
--- a/src/backend/tsearch/wparser.c
+++ b/src/backend/tsearch/wparser.c
@@ -63,7 +63,7 @@ tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid)
 	st->cur = 0;
 	/* lextype takes one dummy argument */
 	st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
-															 (Datum) 0));
+															 NullDatum));
 	funcctx->user_fctx = (void *) st;
 
 	tupdesc = CreateTemplateTupleDesc(3);
@@ -107,7 +107,7 @@ tt_process_call(FuncCallContext *funcctx)
 	if (st->list)
 		pfree(st->list);
 	pfree(st);
-	return (Datum) 0;
+	return NullDatum;
 }
 
 Datum
@@ -124,7 +124,7 @@ ts_token_type_byid(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = tt_process_call(funcctx)) != (Datum) 0)
+	if (DatumGetPointer(result = tt_process_call(funcctx)))
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -147,7 +147,7 @@ ts_token_type_byname(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = tt_process_call(funcctx)) != (Datum) 0)
+	if (DatumGetPointer(result = tt_process_call(funcctx)))
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -251,7 +251,7 @@ prs_process_call(FuncCallContext *funcctx)
 			pfree(st->list);
 		pfree(st);
 	}
-	return (Datum) 0;
+	return NullDatum;
 }
 
 Datum
@@ -271,7 +271,7 @@ ts_parse_byid(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = prs_process_call(funcctx)) != (Datum) 0)
+	if (DatumGetPointer(result = prs_process_call(funcctx)))
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -295,7 +295,7 @@ ts_parse_byname(PG_FUNCTION_ARGS)
 
 	funcctx = SRF_PERCALL_SETUP();
 
-	if ((result = prs_process_call(funcctx)) != (Datum) 0)
+	if (DatumGetPointer(result = prs_process_call(funcctx)))
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index cfd139e6e9..d921ae1acc 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -4695,7 +4695,7 @@ initialize_acl(void)
 		 */
 		CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
 									  RoleMembershipCacheCallback,
-									  (Datum) 0);
+									  NullDatum);
 	}
 }
 
@@ -5275,13 +5275,13 @@ get_rolespec_tuple(const RoleSpec *role)
 			break;
 
 		case ROLESPEC_CURRENT_USER:
-			tuple = SearchSysCache1(AUTHOID, GetUserId());
+			tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId()));
 			if (!HeapTupleIsValid(tuple))
 				elog(ERROR, "cache lookup failed for role %u", GetUserId());
 			break;
 
 		case ROLESPEC_SESSION_USER:
-			tuple = SearchSysCache1(AUTHOID, GetSessionUserId());
+			tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetSessionUserId()));
 			if (!HeapTupleIsValid(tuple))
 				elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
 			break;
diff --git a/src/backend/utils/adt/amutils.c b/src/backend/utils/adt/amutils.c
index e81d6cc056..263dc3b369 100644
--- a/src/backend/utils/adt/amutils.c
+++ b/src/backend/utils/adt/amutils.c
@@ -466,5 +466,5 @@ pg_indexam_progress_phasename(PG_FUNCTION_ARGS)
 	if (!name)
 		PG_RETURN_NULL();
 
-	PG_RETURN_TEXT_P(CStringGetTextDatum(name));
+	PG_RETURN_TEXT_P(name);
 }
diff --git a/src/backend/utils/adt/array_selfuncs.c b/src/backend/utils/adt/array_selfuncs.c
index a0ac949285..772ae99835 100644
--- a/src/backend/utils/adt/array_selfuncs.c
+++ b/src/backend/utils/adt/array_selfuncs.c
@@ -412,7 +412,7 @@ calc_arraycontsel(VariableStatData *vardata, Datum constval,
 	}
 
 	/* If constant was toasted, release the copy we made */
-	if (PointerGetDatum(array) != constval)
+	if (array != (ArrayType *) DatumGetPointer(constval))
 		pfree(array);
 
 	return selec;
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index eafb94b697..51c3d5f06f 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -430,7 +430,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			count_item->frequency = 1;
 
 		/* Free memory allocated while detoasting. */
-		if (PointerGetDatum(array) != value)
+		if (array != (ArrayType *) DatumGetPointer(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 470a480fdd..4277794dbb 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -112,7 +112,7 @@ array_append(PG_FUNCTION_ARGS)
 	eah = fetch_array_arg_replace_nulls(fcinfo, 0);
 	isNull = PG_ARGISNULL(1);
 	if (isNull)
-		newelem = (Datum) 0;
+		newelem = NullDatum;
 	else
 		newelem = PG_GETARG_DATUM(1);
 
@@ -164,7 +164,7 @@ array_prepend(PG_FUNCTION_ARGS)
 
 	isNull = PG_ARGISNULL(0);
 	if (isNull)
-		newelem = (Datum) 0;
+		newelem = NullDatum;
 	else
 		newelem = PG_GETARG_DATUM(0);
 	eah = fetch_array_arg_replace_nulls(fcinfo, 1);
@@ -198,7 +198,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 */
@@ -482,7 +482,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) ? NullDatum : PG_GETARG_DATUM(1);
 
 	state = accumArrayResult(state,
 							 elem,
@@ -666,7 +666,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 = NullDatum;
 		null_search = true;
 	}
 	else
@@ -820,7 +820,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 = NullDatum;
 		null_search = true;
 	}
 	else
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 8fcdf82922..7e8cd63998 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -1879,14 +1879,14 @@ array_get_element(Datum arraydatum,
 	if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 	for (i = 0; i < ndim; i++)
 	{
 		if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
 		{
 			*isNull = true;
-			return (Datum) 0;
+			return NullDatum;
 		}
 	}
 
@@ -1901,7 +1901,7 @@ array_get_element(Datum arraydatum,
 	if (array_get_isnull(arraynullsptr, offset))
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	/*
@@ -1951,14 +1951,14 @@ array_get_element_expanded(Datum arraydatum,
 	if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 	for (i = 0; i < ndim; i++)
 	{
 		if (indx[i] < lb[i] || indx[i] >= (dim[i] + lb[i]))
 		{
 			*isNull = true;
-			return (Datum) 0;
+			return NullDatum;
 		}
 	}
 
@@ -1982,7 +1982,7 @@ array_get_element_expanded(Datum arraydatum,
 	if (dnulls && dnulls[offset])
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	/*
@@ -2665,7 +2665,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] = NullDatum;
 		if (dnulls)
 		{
 			memmove(dnulls + addedbefore, dnulls, eah->nelems * sizeof(bool));
@@ -2679,7 +2679,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] = NullDatum;
 		if (dnulls)
 		{
 			for (i = 0; i < addedafter; i++)
@@ -3490,7 +3490,7 @@ deconstruct_array(ArrayType *array,
 		/* Get source element, checking for NULL */
 		if (bitmap && (*bitmap & bitmask) == 0)
 		{
-			elems[i] = (Datum) 0;
+			elems[i] = NullDatum;
 			if (nulls)
 				nulls[i] = true;
 			else
@@ -4408,7 +4408,7 @@ array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
 		if (array_get_isnull(iterator->nullbitmap, iterator->current_item++))
 		{
 			*isnull = true;
-			*value = (Datum) 0;
+			*value = NullDatum;
 		}
 		else
 		{
@@ -4441,7 +4441,7 @@ array_iterate(ArrayIterator iterator, Datum *value, bool *isnull)
 								 iterator->current_item++))
 			{
 				nulls[i] = true;
-				values[i] = (Datum) 0;
+				values[i] = NullDatum;
 			}
 			else
 			{
@@ -5708,7 +5708,7 @@ array_fill_with_lower_bounds(PG_FUNCTION_ARGS)
 	}
 	else
 	{
-		value = 0;
+		value = NullDatum;
 		isnull = true;
 	}
 
@@ -5747,7 +5747,7 @@ array_fill(PG_FUNCTION_ARGS)
 	}
 	else
 	{
-		value = 0;
+		value = NullDatum;
 		isnull = true;
 	}
 
@@ -6338,7 +6338,7 @@ array_remove(PG_FUNCTION_ARGS)
 
 	array = array_replace_internal(array,
 								   search, search_isnull,
-								   (Datum) 0, true,
+								   NullDatum, true,
 								   true, PG_GET_COLLATION(),
 								   fcinfo);
 	PG_RETURN_ARRAYTYPE_P(array);
diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c
index 81ea5a48e5..8a09e68a90 100644
--- a/src/backend/utils/adt/datum.c
+++ b/src/backend/utils/adt/datum.c
@@ -230,7 +230,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
 	{
@@ -288,15 +288,15 @@ datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
 							 len1 - VARHDRSZ) == 0);
 
 			/* Only free memory if it's a copy made here. */
-			if ((Pointer) arg1val != (Pointer) value1)
+			if ((Pointer) arg1val != (Pointer) value1.value)
 				pfree(arg1val);
-			if ((Pointer) arg2val != (Pointer) value2)
+			if ((Pointer) arg2val != (Pointer) value2.value)
 				pfree(arg2val);
 		}
 	}
 	else if (typByVal)
 	{
-		result = (value1 == value2);
+		result = (value1.value == value2.value);
 	}
 	else
 	{
@@ -438,7 +438,7 @@ datumRestore(char **start_address, bool *isnull)
 	if (header == -2)
 	{
 		*isnull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	/* OK, datum is not null. */
diff --git a/src/backend/utils/adt/expandedrecord.c b/src/backend/utils/adt/expandedrecord.c
index 166c863026..9a584f10e7 100644
--- a/src/backend/utils/adt/expandedrecord.c
+++ b/src/backend/utils/adt/expandedrecord.c
@@ -1068,7 +1068,7 @@ expanded_record_fetch_field(ExpandedRecordHeader *erh, int fnumber,
 		if (ExpandedRecordIsEmpty(erh))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return NullDatum;
 		}
 		/* Make sure we have deconstructed form */
 		deconstruct_expanded_record(erh);
@@ -1076,7 +1076,7 @@ expanded_record_fetch_field(ExpandedRecordHeader *erh, int fnumber,
 		if (unlikely(fnumber > erh->nfields))
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return NullDatum;
 		}
 		*isnull = erh->dnulls[fnumber - 1];
 		return erh->dvalues[fnumber - 1];
@@ -1087,7 +1087,7 @@ expanded_record_fetch_field(ExpandedRecordHeader *erh, int fnumber,
 		if (erh->fvalue == NULL)
 		{
 			*isnull = true;
-			return (Datum) 0;
+			return NullDatum;
 		}
 		/* heap_getsysattr doesn't actually use tupdesc, so just pass null */
 		return heap_getsysattr(erh->fvalue, fnumber, NULL, isnull);
@@ -1583,7 +1583,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(NullDatum, true,
 					 erh->er_decltypeid,
 					 &erh->er_domaininfo,
 					 erh->hdr.eoh_context);
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 26d293709a..0834c24e7f 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -1985,7 +1985,7 @@ json_agg_transfn(PG_FUNCTION_ARGS)
 	/* fast path for NULLs */
 	if (PG_ARGISNULL(1))
 	{
-		datum_to_json((Datum) 0, true, state->str, JSONTYPE_NULL,
+		datum_to_json(NullDatum, true, state->str, JSONTYPE_NULL,
 					  InvalidOid, false);
 		PG_RETURN_POINTER(state);
 	}
@@ -2117,7 +2117,7 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
 	appendStringInfoString(state->str, " : ");
 
 	if (PG_ARGISNULL(2))
-		arg = (Datum) 0;
+		arg = NullDatum;
 	else
 		arg = PG_GETARG_DATUM(2);
 
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 69f41ab455..799a5d7c77 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -1535,7 +1535,7 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
 
 	/* turn the argument into jsonb in the normal function context */
 
-	val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
+	val = PG_ARGISNULL(1) ? NullDatum : PG_GETARG_DATUM(1);
 
 	memset(&elem, 0, sizeof(JsonbInState));
 
@@ -1715,7 +1715,7 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
 
 	jbkey = JsonbValueToJsonb(elem.res);
 
-	val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
+	val = PG_ARGISNULL(2) ? NullDatum : 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 e8d54e70b8..208e198ad9 100644
--- a/src/backend/utils/adt/jsonb_gin.c
+++ b/src/backend/utils/adt/jsonb_gin.c
@@ -897,8 +897,8 @@ gin_extract_jsonb_query(PG_FUNCTION_ARGS)
 			if (key_nulls[i])
 				continue;
 			entries[j++] = make_text_key(JGINFLAG_KEY,
-										 VARDATA(key_datums[i]),
-										 VARSIZE(key_datums[i]) - VARHDRSZ);
+										 VARDATA(DatumGetPointer(key_datums[i])),
+										 VARSIZE(DatumGetPointer(key_datums[i])) - VARHDRSZ);
 		}
 
 		*nentries = j;
@@ -1402,7 +1402,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 = NullDatum;		/* keep compiler quiet */
 			break;
 	}
 
diff --git a/src/backend/utils/adt/jsonb_op.c b/src/backend/utils/adt/jsonb_op.c
index a64206eeb1..ff4fe8afd1 100644
--- a/src/backend/utils/adt/jsonb_op.c
+++ b/src/backend/utils/adt/jsonb_op.c
@@ -64,8 +64,8 @@ jsonb_exists_any(PG_FUNCTION_ARGS)
 			continue;
 
 		strVal.type = jbvString;
-		strVal.val.string.val = VARDATA(key_datums[i]);
-		strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
+		strVal.val.string.val = VARDATA(DatumGetPointer(key_datums[i]));
+		strVal.val.string.len = VARSIZE(DatumGetPointer(key_datums[i])) - VARHDRSZ;
 
 		if (findJsonbValueFromContainer(&jb->root,
 										JB_FOBJECT | JB_FARRAY,
@@ -97,8 +97,8 @@ jsonb_exists_all(PG_FUNCTION_ARGS)
 			continue;
 
 		strVal.type = jbvString;
-		strVal.val.string.val = VARDATA(key_datums[i]);
-		strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
+		strVal.val.string.val = VARDATA(DatumGetPointer(key_datums[i]));
+		strVal.val.string.len = VARSIZE(DatumGetPointer(key_datums[i])) - VARHDRSZ;
 
 		if (findJsonbValueFromContainer(&jb->root,
 										JB_FOBJECT | JB_FARRAY,
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index fe351edb2b..3d5a44e425 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -1457,8 +1457,8 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
 		{
 			jbvp = findJsonbValueFromContainerLen(container,
 												  JB_FOBJECT,
-												  VARDATA(pathtext[i]),
-												  VARSIZE(pathtext[i]) - VARHDRSZ);
+												  VARDATA(DatumGetPointer(pathtext[i])),
+												  VARSIZE(DatumGetPointer(pathtext[i])) - VARHDRSZ);
 		}
 		else if (have_array)
 		{
@@ -1756,7 +1756,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] = NullDatum;
 				}
 				else
 				{
@@ -1914,7 +1914,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] = NullDatum;
 	}
 	else if (_state->next_scalar)
 	{
@@ -2066,7 +2066,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] = NullDatum;
 				}
 				else
 				{
@@ -2228,7 +2228,7 @@ elements_array_element_end(void *state, bool isnull)
 	if (isnull && _state->normalize_results)
 	{
 		nulls[0] = true;
-		values[0] = (Datum) NULL;
+		values[0] = NullDatum;
 	}
 	else if (_state->next_scalar)
 	{
@@ -2761,7 +2761,7 @@ populate_composite(CompositeIOData *io,
 	update_cached_tupdesc(io, mcxt);
 
 	if (isnull)
-		result = (Datum) 0;
+		result = NullDatum;
 	else
 	{
 		HeapTupleHeader tuple;
@@ -2882,7 +2882,7 @@ populate_domain(DomainIOData *io,
 	Datum		res;
 
 	if (isnull)
-		res = (Datum) 0;
+		res = NullDatum;
 	else
 	{
 		res = populate_record_field(io->base_io,
@@ -3021,7 +3021,7 @@ populate_record_field(ColumnIOData *col,
 	if (*isnull &&
 		typcat != TYPECAT_DOMAIN &&
 		typcat != TYPECAT_COMPOSITE_DOMAIN)
-		return (Datum) 0;
+		return NullDatum;
 
 	switch (typcat)
 	{
@@ -3046,7 +3046,7 @@ populate_record_field(ColumnIOData *col,
 
 		default:
 			elog(ERROR, "unrecognized type category '%c'", typcat);
-			return (Datum) 0;
+			return NullDatum;
 	}
 }
 
@@ -3152,7 +3152,7 @@ populate_record(TupleDesc tupdesc,
 	{
 		for (i = 0; i < ncolumns; ++i)
 		{
-			values[i] = (Datum) 0;
+			values[i] = NullDatum;
 			nulls[i] = true;
 		}
 	}
@@ -3189,7 +3189,7 @@ populate_record(TupleDesc tupdesc,
 										  att->atttypmod,
 										  colname,
 										  mcxt,
-										  nulls[i] ? (Datum) 0 : values[i],
+										  nulls[i] ? NullDatum : values[i],
 										  &field,
 										  &nulls[i]);
 	}
@@ -4322,8 +4322,8 @@ jsonb_delete_array(PG_FUNCTION_ARGS)
 				if (keys_nulls[i])
 					continue;
 
-				keyptr = VARDATA_ANY(keys_elems[i]);
-				keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
+				keyptr = VARDATA_ANY(DatumGetPointer(keys_elems[i]));
+				keylen = VARSIZE_ANY_EXHDR(DatumGetPointer(keys_elems[i]));
 				if (keylen == v.val.string.len &&
 					memcmp(keyptr, v.val.string.val, keylen) == 0)
 				{
@@ -4751,8 +4751,8 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
 		JsonbValue	newkey;
 
 		newkey.type = jbvString;
-		newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
-		newkey.val.string.val = VARDATA_ANY(path_elems[level]);
+		newkey.val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(path_elems[level]));
+		newkey.val.string.val = VARDATA_ANY(DatumGetPointer(path_elems[level]));
 
 		(void) pushJsonbValue(st, WJB_KEY, &newkey);
 		addJsonbToParseState(st, newval);
@@ -4765,8 +4765,8 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
 		Assert(r == WJB_KEY);
 
 		if (!done &&
-			k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) &&
-			memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]),
+			k.val.string.len == VARSIZE_ANY_EXHDR(DatumGetPointer(path_elems[level])) &&
+			memcmp(k.val.string.val, VARDATA_ANY(DatumGetPointer(path_elems[level])),
 				   k.val.string.len) == 0)
 		{
 			if (level == path_len - 1)
@@ -4805,8 +4805,8 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
 				JsonbValue	newkey;
 
 				newkey.type = jbvString;
-				newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]);
-				newkey.val.string.val = VARDATA_ANY(path_elems[level]);
+				newkey.val.string.len = VARSIZE_ANY_EXHDR(DatumGetPointer(path_elems[level]));
+				newkey.val.string.val = VARDATA_ANY(DatumGetPointer(path_elems[level]));
 
 				(void) pushJsonbValue(st, WJB_KEY, &newkey);
 				addJsonbToParseState(st, newval);
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index ffd1970f58..c4609d7ea1 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -351,15 +351,15 @@ pg_lock_status(PG_FUNCTION_ARGS)
 		values[0] = CStringGetTextDatum(PredicateLockTagTypeNames[lockType]);
 
 		/* lock target */
-		values[1] = GET_PREDICATELOCKTARGETTAG_DB(*predTag);
-		values[2] = GET_PREDICATELOCKTARGETTAG_RELATION(*predTag);
+		values[1] = ObjectIdGetDatum(GET_PREDICATELOCKTARGETTAG_DB(*predTag));
+		values[2] = ObjectIdGetDatum(GET_PREDICATELOCKTARGETTAG_RELATION(*predTag));
 		if (lockType == PREDLOCKTAG_TUPLE)
-			values[4] = GET_PREDICATELOCKTARGETTAG_OFFSET(*predTag);
+			values[4] = ObjectIdGetDatum(GET_PREDICATELOCKTARGETTAG_OFFSET(*predTag));
 		else
 			nulls[4] = true;
 		if ((lockType == PREDLOCKTAG_TUPLE) ||
 			(lockType == PREDLOCKTAG_PAGE))
-			values[3] = GET_PREDICATELOCKTARGETTAG_PAGE(*predTag);
+			values[3] = ObjectIdGetDatum(GET_PREDICATELOCKTARGETTAG_PAGE(*predTag));
 		else
 			nulls[3] = true;
 
@@ -596,7 +596,7 @@ pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
 	 * acquire heavyweight locks.
 	 */
 	blocking_pids_a =
-		DatumGetArrayTypeP(DirectFunctionCall1(pg_blocking_pids, blocked_pid));
+		DatumGetArrayTypeP(DirectFunctionCall1(pg_blocking_pids, Int32GetDatum(blocked_pid)));
 
 	Assert(ARR_ELEMTYPE(blocking_pids_a) == INT4OID);
 	Assert(!array_contains_nulls(blocking_pids_a));
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index 3bfeb75fa2..a0247fcdc2 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -413,9 +413,9 @@ macaddr_fast_cmp(Datum x, Datum y, SortSupport ssup)
 static int
 macaddr_cmp_abbrev(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 0;
 	else
 		return -1;
@@ -526,9 +526,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)));
@@ -542,7 +542,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 = Int32GetDatum(DatumBigEndianToNative(res.value));
 
 	return res;
 }
diff --git a/src/backend/utils/adt/network_gist.c b/src/backend/utils/adt/network_gist.c
index 1a8dfb1772..f03e28b935 100644
--- a/src/backend/utils/adt/network_gist.c
+++ b/src/backend/utils/adt/network_gist.c
@@ -565,7 +565,7 @@ inet_gist_compress(PG_FUNCTION_ARGS)
 		}
 		else
 		{
-			gistentryinit(*retval, (Datum) 0,
+			gistentryinit(*retval, NullDatum,
 						  entry->rel, entry->page,
 						  entry->offset, false);
 		}
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 201784bbf6..a430e4b0c4 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -356,12 +356,12 @@ 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) (MakeDatum(X))
+#define DatumGetNumericAbbrev(X) ((int64) (X).value)
 #define NUMERIC_ABBREV_NAN		 NumericAbbrevGetDatum(PG_INT64_MIN)
 #else
-#define NumericAbbrevGetDatum(X) ((Datum) (X))
-#define DatumGetNumericAbbrev(X) ((int32) (X))
+#define NumericAbbrevGetDatum(X) (MakeDatum(X))
+#define DatumGetNumericAbbrev(X) ((int32) (X).value)
 #define NUMERIC_ABBREV_NAN		 NumericAbbrevGetDatum(PG_INT32_MIN)
 #endif
 
@@ -2326,7 +2326,7 @@ hash_numeric(PG_FUNCTION_ARGS)
 						  hash_len * sizeof(NumericDigit));
 
 	/* Mix in the weight, via XOR */
-	result = digit_hash ^ weight;
+	result = UInt32GetDatum(DatumGetUInt32(digit_hash) ^ weight);
 
 	PG_RETURN_DATUM(result);
 }
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 4db2d0d0e1..8283bffa82 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -732,7 +732,7 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)
 	Datum	   *result_datum;
 	bool	   *result_isnull;
 	int64		rownum = 0;
-	Datum		val = (Datum) 0;
+	Datum		val = NullDatum;
 	bool		isnull = true;
 	int			i;
 
@@ -783,7 +783,7 @@ percentile_disc_multi_final(PG_FUNCTION_ARGS)
 		if (pct_info[i].first_row > 0)
 			break;
 
-		result_datum[idx] = (Datum) 0;
+		result_datum[idx] = NullDatum;
 		result_isnull[idx] = true;
 	}
 
@@ -853,8 +853,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 = NullDatum;
+	Datum		second_val = NullDatum;
 	bool		isnull;
 	int			i;
 
@@ -907,7 +907,7 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo,
 		if (pct_info[i].first_row > 0)
 			break;
 
-		result_datum[idx] = (Datum) 0;
+		result_datum[idx] = NullDatum;
 		result_isnull[idx] = true;
 	}
 
@@ -1029,14 +1029,14 @@ mode_final(PG_FUNCTION_ARGS)
 	OSAPerGroupState *osastate;
 	Datum		val;
 	bool		isnull;
-	Datum		mode_val = (Datum) 0;
+	Datum		mode_val = NullDatum;
 	int64		mode_freq = 0;
-	Datum		last_val = (Datum) 0;
+	Datum		last_val = NullDatum;
 	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 = NullDatum;
+	Datum		last_abbrev_val = NullDatum;
 	bool		shouldfree;
 
 	Assert(AggCheckCallContext(fcinfo, NULL) == AGG_CONTEXT_AGGREGATE);
@@ -1083,7 +1083,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 */
@@ -1294,8 +1294,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 = NullDatum;
+	Datum		abbrevOld = NullDatum;
 	TupleTableSlot *slot;
 	TupleTableSlot *extraslot;
 	TupleTableSlot *slot2;
@@ -1397,7 +1397,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/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 05240bfd14..5fd2b2dee3 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -537,7 +537,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 /*
@@ -914,7 +914,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 
@@ -1145,8 +1145,8 @@ pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
 
 	clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
 
-	PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
-										 CStringGetDatum(remote_host)));
+	PG_RETURN_DATUM(DirectFunctionCall1(inet_in,
+										CStringGetDatum(remote_host)));
 }
 
 Datum
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index e5c7e5c7ee..492669456c 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -206,7 +206,7 @@ range_recv(PG_FUNCTION_ARGS)
 		pfree(bound_buf.data);
 	}
 	else
-		lower.val = (Datum) 0;
+		lower.val = NullDatum;
 
 	if (RANGE_HAS_UBOUND(flags))
 	{
@@ -224,7 +224,7 @@ range_recv(PG_FUNCTION_ARGS)
 		pfree(bound_buf.data);
 	}
 	else
-		upper.val = (Datum) 0;
+		upper.val = NullDatum;
 
 	pq_getmsgend(buf);
 
@@ -270,8 +270,8 @@ range_send(PG_FUNCTION_ARGS)
 	{
 		Datum		bound = PointerGetDatum(SendFunctionCall(&cache->proc,
 															 lower.val));
-		uint32		bound_len = VARSIZE(bound) - VARHDRSZ;
-		char	   *bound_data = VARDATA(bound);
+		uint32		bound_len = VARSIZE(DatumGetPointer(bound)) - VARHDRSZ;
+		char	   *bound_data = VARDATA(DatumGetPointer(bound));
 
 		pq_sendint32(buf, bound_len);
 		pq_sendbytes(buf, bound_data, bound_len);
@@ -281,8 +281,8 @@ range_send(PG_FUNCTION_ARGS)
 	{
 		Datum		bound = PointerGetDatum(SendFunctionCall(&cache->proc,
 															 upper.val));
-		uint32		bound_len = VARSIZE(bound) - VARHDRSZ;
-		char	   *bound_data = VARDATA(bound);
+		uint32		bound_len = VARSIZE(DatumGetPointer(bound)) - VARHDRSZ;
+		char	   *bound_data = VARDATA(DatumGetPointer(bound));
 
 		pq_sendint32(buf, bound_len);
 		pq_sendbytes(buf, bound_data, bound_len);
@@ -370,12 +370,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) ? NullDatum : 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) ? NullDatum : arg2;
 	upper.infinite = PG_ARGISNULL(1);
 	upper.inclusive = false;
 	upper.lower = false;
@@ -407,12 +407,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) ? NullDatum : 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) ? NullDatum : arg2;
 	upper.infinite = PG_ARGISNULL(1);
 	upper.inclusive = (flags & RANGE_UB_INC) != 0;
 	upper.lower = false;
@@ -1047,8 +1047,8 @@ range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
 		return r1;
 
 	if (strict &&
-		!DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
-		!DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
+		!range_overlaps_internal(typcache, r1, r2) &&
+		!range_adjacent_internal(typcache, r1, r2))
 		ereport(ERROR,
 				(errcode(ERRCODE_DATA_EXCEPTION),
 				 errmsg("result of range union would not be contiguous")));
@@ -1187,7 +1187,7 @@ range_cmp(PG_FUNCTION_ARGS)
 Datum
 range_lt(PG_FUNCTION_ARGS)
 {
-	int			cmp = range_cmp(fcinfo);
+	int			cmp = DatumGetInt32(range_cmp(fcinfo));
 
 	PG_RETURN_BOOL(cmp < 0);
 }
@@ -1195,7 +1195,7 @@ range_lt(PG_FUNCTION_ARGS)
 Datum
 range_le(PG_FUNCTION_ARGS)
 {
-	int			cmp = range_cmp(fcinfo);
+	int			cmp = DatumGetInt32(range_cmp(fcinfo));
 
 	PG_RETURN_BOOL(cmp <= 0);
 }
@@ -1203,7 +1203,7 @@ range_le(PG_FUNCTION_ARGS)
 Datum
 range_ge(PG_FUNCTION_ARGS)
 {
-	int			cmp = range_cmp(fcinfo);
+	int			cmp = DatumGetInt32(range_cmp(fcinfo));
 
 	PG_RETURN_BOOL(cmp >= 0);
 }
@@ -1211,7 +1211,7 @@ range_ge(PG_FUNCTION_ARGS)
 Datum
 range_gt(PG_FUNCTION_ARGS)
 {
-	int			cmp = range_cmp(fcinfo);
+	int			cmp = DatumGetInt32(range_cmp(fcinfo));
 
 	PG_RETURN_BOOL(cmp > 0);
 }
@@ -1273,7 +1273,7 @@ hash_range(PG_FUNCTION_ARGS)
 		upper_hash = 0;
 
 	/* Merge hashes of flags and bounds */
-	result = hash_uint32((uint32) flags);
+	result = DatumGetUInt32(hash_uint32((uint32) flags));
 	result ^= lower_hash;
 	result = (result << 1) | (result >> 31);
 	result ^= upper_hash;
@@ -1729,7 +1729,7 @@ range_deserialize(TypeCacheEntry *typcache, RangeType *range,
 		ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
 	}
 	else
-		lbound = (Datum) 0;
+		lbound = NullDatum;
 
 	/* fetch upper bound, if any */
 	if (RANGE_HAS_UBOUND(flags))
@@ -1739,7 +1739,7 @@ range_deserialize(TypeCacheEntry *typcache, RangeType *range,
 		/* no need for att_addlength_pointer */
 	}
 	else
-		ubound = (Datum) 0;
+		ubound = NullDatum;
 
 	/* emit results */
 
@@ -1946,12 +1946,12 @@ make_empty_range(TypeCacheEntry *typcache)
 	RangeBound	lower;
 	RangeBound	upper;
 
-	lower.val = (Datum) 0;
+	lower.val = NullDatum;
 	lower.infinite = false;
 	lower.inclusive = false;
 	lower.lower = true;
 
-	upper.val = (Datum) 0;
+	upper.val = NullDatum;
 	upper.infinite = false;
 	upper.inclusive = false;
 	upper.lower = false;
diff --git a/src/backend/utils/adt/rangetypes_spgist.c b/src/backend/utils/adt/rangetypes_spgist.c
index 8bb730ce8e..00e1cd82c0 100644
--- a/src/backend/utils/adt/rangetypes_spgist.c
+++ b/src/backend/utils/adt/rangetypes_spgist.c
@@ -417,7 +417,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
 		/* This node has a centroid. Fetch it. */
 		centroid = DatumGetRangeTypeP(in->prefixDatum);
 		typcache = range_get_typcache(fcinfo,
-									  RangeTypeGetOid(DatumGetRangeTypeP(centroid)));
+									  RangeTypeGetOid(centroid));
 		range_deserialize(typcache, centroid, &centroidLower, &centroidUpper,
 						  &centroidEmpty);
 
@@ -558,7 +558,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
 					 */
 					if (in->traversalValue)
 					{
-						prevCentroid = DatumGetRangeTypeP(in->traversalValue);
+						prevCentroid = in->traversalValue;
 						range_deserialize(typcache, prevCentroid,
 										  &prevLower, &prevUpper, &prevEmpty);
 					}
@@ -760,7 +760,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
 				 * because it's range
 				 */
 				previousCentroid = datumCopy(in->prefixDatum, false, -1);
-				out->traversalValues[out->nNodes] = (void *) previousCentroid;
+				out->traversalValues[out->nNodes] = DatumGetPointer(previousCentroid);
 			}
 			out->nodeNumbers[out->nNodes] = i - 1;
 			out->nNodes++;
diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c
index 90a9197792..20cefc6250 100644
--- a/src/backend/utils/adt/regexp.c
+++ b/src/backend/utils/adt/regexp.c
@@ -1245,7 +1245,7 @@ build_regexp_match_result(regexp_matches_ctx *matchctx)
 
 		if (so < 0 || eo < 0)
 		{
-			elems[i] = (Datum) 0;
+			elems[i] = NullDatum;
 			nulls[i] = true;
 		}
 		else if (buf)
@@ -1380,7 +1380,7 @@ regexp_split_to_array(PG_FUNCTION_ARGS)
 		splitctx->next_match++;
 	}
 
-	PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));
+	PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
 }
 
 /* This is separate to keep the opr_sanity regression test from complaining */
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 44a6eef5bb..b791aee412 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -2548,7 +2548,7 @@ ri_InitHashTables(void)
 	/* Arrange to flush cache on pg_constraint changes */
 	CacheRegisterSyscacheCallback(CONSTROID,
 								  InvalidateConstraintCacheCallBack,
-								  (Datum) 0);
+								  NullDatum);
 
 	memset(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(RI_QueryKey);
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index aa7ec8735c..fb67eb26cc 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -168,7 +168,7 @@ record_in(PG_FUNCTION_ARGS)
 		/* Ignore dropped columns in datatype, but fill with nulls */
 		if (att->attisdropped)
 		{
-			values[i] = (Datum) 0;
+			values[i] = NullDatum;
 			nulls[i] = true;
 			continue;
 		}
@@ -546,7 +546,7 @@ record_recv(PG_FUNCTION_ARGS)
 		/* Ignore dropped columns in datatype, but fill with nulls */
 		if (att->attisdropped)
 		{
-			values[i] = (Datum) 0;
+			values[i] = NullDatum;
 			nulls[i] = true;
 			continue;
 		}
@@ -1461,15 +1461,15 @@ record_image_cmp(FunctionCallInfo fcinfo)
 				if ((cmpresult == 0) && (len1 != len2))
 					cmpresult = (len1 < len2) ? -1 : 1;
 
-				if ((Pointer) arg1val != (Pointer) values1[i1])
+				if ((Pointer) arg1val != DatumGetPointer(values1[i1]))
 					pfree(arg1val);
-				if ((Pointer) arg2val != (Pointer) values2[i2])
+				if ((Pointer) arg2val != DatumGetPointer(values2[i2]))
 					pfree(arg2val);
 			}
 			else 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
 			{
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 4ca0ed2bbb..937f0b2d74 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2988,7 +2988,7 @@ print_function_arguments(StringInfo buf, HeapTuple proctup,
 		HeapTuple	aggtup;
 		Form_pg_aggregate agg;
 
-		aggtup = SearchSysCache1(AGGFNOID, proc->oid);
+		aggtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(proc->oid));
 		if (!HeapTupleIsValid(aggtup))
 			elog(ERROR, "cache lookup failed for aggregate %u",
 				 proc->oid);
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 7eba59eff3..019df23b85 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -4986,8 +4986,8 @@ static bool
 get_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop,
 				   Datum *min, Datum *max)
 {
-	Datum		tmin = 0;
-	Datum		tmax = 0;
+	Datum		tmin = NullDatum;
+	Datum		tmax = NullDatum;
 	bool		have_data = false;
 	int16		typLen;
 	bool		typByVal;
@@ -5221,7 +5221,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 */
+								   NullDatum);	/* constant */
 
 			/* If min is requested ... */
 			if (min)
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index 039ddc86a8..968e29d410 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -346,7 +346,7 @@ currtid_for_view(Relation viewrel, ItemPointer tid)
 		}
 	}
 	elog(ERROR, "currtid cannot handle this view");
-	return (Datum) 0;
+	return NullDatum;
 }
 
 Datum
diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c
index 4f256260fd..9ef302b2ae 100644
--- a/src/backend/utils/adt/tsgistidx.c
+++ b/src/backend/utils/adt/tsgistidx.c
@@ -79,7 +79,7 @@ gtsvectorin(PG_FUNCTION_ARGS)
 	ereport(ERROR,
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("gtsvector_in not implemented")));
-	PG_RETURN_DATUM(0);
+	PG_RETURN_DATUM(NullDatum);
 }
 
 #define SINGOUTSTR	"%d true bits, %d false bits"
@@ -91,7 +91,7 @@ static int	outbuf_maxlen = 0;
 Datum
 gtsvectorout(PG_FUNCTION_ARGS)
 {
-	SignTSVector *key = (SignTSVector *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
+	SignTSVector *key = (SignTSVector *) PG_GETARG_VARLENA_P(0);
 	char	   *outbuf;
 
 	if (outbuf_maxlen == 0)
diff --git a/src/backend/utils/adt/tsquery_op.c b/src/backend/utils/adt/tsquery_op.c
index 1f63d9b6a9..7604c9517f 100644
--- a/src/backend/utils/adt/tsquery_op.c
+++ b/src/backend/utils/adt/tsquery_op.c
@@ -147,7 +147,7 @@ tsquery_phrase_distance(PG_FUNCTION_ARGS)
 Datum
 tsquery_phrase(PG_FUNCTION_ARGS)
 {
-	PG_RETURN_POINTER(DirectFunctionCall3(
+	PG_RETURN_DATUM(DirectFunctionCall3(
 										  tsquery_phrase_distance,
 										  PG_GETARG_DATUM(0),
 										  PG_GETARG_DATUM(1),
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index 4f7bafd142..026e526423 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -320,8 +320,8 @@ tsvector_setweight_by_filter(PG_FUNCTION_ARGS)
 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 					 errmsg("lexeme array may not contain nulls")));
 
-		lex = VARDATA(dlexemes[i]);
-		lex_len = VARSIZE(dlexemes[i]) - VARHDRSZ;
+		lex = VARDATA(DatumGetPointer(dlexemes[i]));
+		lex_len = VARSIZE(DatumGetPointer(dlexemes[i])) - VARHDRSZ;
 		lex_pos = tsvector_bsearch(tsout, lex, lex_len);
 
 		if (lex_pos >= 0 && (j = POSDATALEN(tsout, entry + lex_pos)) != 0)
@@ -436,10 +436,10 @@ compare_text_lexemes(const void *va, const void *vb)
 {
 	Datum		a = *((const Datum *) va);
 	Datum		b = *((const Datum *) vb);
-	char	   *alex = VARDATA_ANY(a);
-	int			alex_len = VARSIZE_ANY_EXHDR(a);
-	char	   *blex = VARDATA_ANY(b);
-	int			blex_len = VARSIZE_ANY_EXHDR(b);
+	char	   *alex = VARDATA_ANY(DatumGetPointer(a));
+	int			alex_len = VARSIZE_ANY_EXHDR(DatumGetPointer(a));
+	char	   *blex = VARDATA_ANY(DatumGetPointer(b));
+	int			blex_len = VARSIZE_ANY_EXHDR(DatumGetPointer(b));
 
 	return tsCompareString(alex, alex_len, blex, blex_len, false);
 }
@@ -607,8 +607,8 @@ tsvector_delete_arr(PG_FUNCTION_ARGS)
 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 					 errmsg("lexeme array may not contain nulls")));
 
-		lex = VARDATA(dlexemes[i]);
-		lex_len = VARSIZE(dlexemes[i]) - VARHDRSZ;
+		lex = VARDATA(DatumGetPointer(dlexemes[i]));
+		lex_len = VARSIZE(DatumGetPointer(dlexemes[i])) - VARHDRSZ;
 		lex_pos = tsvector_bsearch(tsin, lex, lex_len);
 
 		if (lex_pos >= 0)
@@ -791,7 +791,7 @@ array_to_tsvector(PG_FUNCTION_ARGS)
 
 	/* Calculate space needed for surviving lexemes. */
 	for (i = 0; i < nitems; i++)
-		datalen += VARSIZE(dlexemes[i]) - VARHDRSZ;
+		datalen += VARSIZE(DatumGetPointer(dlexemes[i])) - VARHDRSZ;
 	tslen = CALCDATASIZE(nitems, datalen);
 
 	/* Allocate and fill tsvector. */
@@ -803,8 +803,8 @@ array_to_tsvector(PG_FUNCTION_ARGS)
 	cur = STRPTR(tsout);
 	for (i = 0; i < nitems; i++)
 	{
-		char	   *lex = VARDATA(dlexemes[i]);
-		int			lex_len = VARSIZE(dlexemes[i]) - VARHDRSZ;
+		char	   *lex = VARDATA(DatumGetPointer(dlexemes[i]));
+		int			lex_len = VARSIZE(DatumGetPointer(dlexemes[i])) - VARHDRSZ;
 
 		memcpy(cur, lex, lex_len);
 		arrout[i].haspos = 0;
@@ -2281,7 +2281,7 @@ ts_process_call(FuncCallContext *funcctx)
 		return result;
 	}
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 static TSVectorStat *
@@ -2393,7 +2393,7 @@ ts_stat1(PG_FUNCTION_ARGS)
 	}
 
 	funcctx = SRF_PERCALL_SETUP();
-	if ((result = ts_process_call(funcctx)) != (Datum) 0)
+	if (DatumGetPointer(result = ts_process_call(funcctx)))
 		SRF_RETURN_NEXT(funcctx, result);
 	SRF_RETURN_DONE(funcctx);
 }
@@ -2420,7 +2420,7 @@ ts_stat2(PG_FUNCTION_ARGS)
 	}
 
 	funcctx = SRF_PERCALL_SETUP();
-	if ((result = ts_process_call(funcctx)) != (Datum) 0)
+	if (DatumGetPointer(result = ts_process_call(funcctx)))
 		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 589c2d51dd..97e1fcd7b4 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -284,9 +284,9 @@ uuid_fast_cmp(Datum x, Datum y, SortSupport ssup)
 static int
 uuid_cmp_abbrev(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 0;
 	else
 		return -1;
@@ -379,9 +379,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)));
@@ -395,7 +395,7 @@ uuid_abbrev_convert(Datum original, SortSupport ssup)
 	 * 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 = UInt32GetDatum(DatumBigEndianToNative(res.value));
 
 	return res;
 }
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 0864838867..b7378866b6 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -663,13 +663,13 @@ text_length(Datum str)
 {
 	/* fastpath when max encoding length is one */
 	if (pg_database_encoding_max_length() == 1)
-		PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ);
+		return toast_raw_datum_size(str) - VARHDRSZ;
 	else
 	{
 		text	   *t = DatumGetTextPP(str);
 
-		PG_RETURN_INT32(pg_mbstrlen_with_len(VARDATA_ANY(t),
-											 VARSIZE_ANY_EXHDR(t)));
+		return pg_mbstrlen_with_len(VARDATA_ANY(t),
+									VARSIZE_ANY_EXHDR(t));
 	}
 }
 
@@ -2133,9 +2133,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;
@@ -2170,9 +2170,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;
@@ -2213,9 +2213,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;
@@ -2400,9 +2400,9 @@ varstrcmp_abbrev(Datum x, Datum y, SortSupport ssup)
 	 * authoritatively, for the same reason that there is a strcoll()
 	 * tie-breaker call to strcmp() in varstr_cmp().
 	 */
-	if (x > y)
+	if (x.value > y.value)
 		return 1;
-	else if (x == y)
+	else if (x.value == y.value)
 		return 0;
 	else
 		return -1;
@@ -2619,8 +2619,8 @@ varstr_abbrev_convert(Datum original, SortSupport ssup)
 		uint32		lohalf,
 					hihalf;
 
-		lohalf = (uint32) res;
-		hihalf = (uint32) (res >> 32);
+		lohalf = DatumGetUInt32(res);
+		hihalf = (uint32) (DatumGetUInt64(res) >> 32);
 		hash = DatumGetUInt32(hash_uint32(lohalf ^ hihalf));
 	}
 #else							/* SIZEOF_DATUM != 8 */
@@ -2641,10 +2641,10 @@ done:
 	 * 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 = UInt32GetDatum(DatumBigEndianToNative(res.value));
 
 	/* Don't leak memory here */
-	if (PointerGetDatum(authoritative) != original)
+	if (PointerGetDatum(authoritative).value != original.value)
 		pfree(authoritative);
 
 	return res;
@@ -4840,8 +4840,7 @@ text_to_array_internal(PG_FUNCTION_ARGS)
 		}
 	}
 
-	PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate,
-										  CurrentMemoryContext));
+	PG_RETURN_DATUM(makeArrayResult(astate, CurrentMemoryContext));
 }
 
 /*
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index d43c3055f3..cbc4af1cbd 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -274,7 +274,7 @@ xml_in(PG_FUNCTION_ARGS)
 	PG_RETURN_XML_P(vardata);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif
 }
 
@@ -409,7 +409,7 @@ xml_recv(PG_FUNCTION_ARGS)
 	PG_RETURN_XML_P(result);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif
 }
 
@@ -498,7 +498,7 @@ xmlcomment(PG_FUNCTION_ARGS)
 	PG_RETURN_XML_P(stringinfo_to_xmltype(&buf));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif
 }
 
@@ -880,7 +880,7 @@ xmlvalidate(PG_FUNCTION_ARGS)
 	ereport(ERROR,
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("xmlvalidate is not implemented")));
-	return 0;
+	return NullDatum;
 }
 
 
@@ -3970,7 +3970,7 @@ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
 		default:
 			elog(ERROR, "xpath expression result type %d is unsupported",
 				 xpathobj->type);
-			return 0;			/* keep compiler quiet */
+			return NullDatum;		/* keep compiler quiet */
 	}
 
 	/* Common code for scalar-value cases */
@@ -4199,7 +4199,7 @@ xpath(PG_FUNCTION_ARGS)
 	PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif
 }
 
@@ -4221,7 +4221,7 @@ xmlexists(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(res_nitems > 0);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif
 }
 
@@ -4245,7 +4245,7 @@ xpath_exists(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(res_nitems > 0);
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif
 }
 
@@ -4289,7 +4289,7 @@ xml_is_well_formed(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(wellformed_xml(data, xmloption));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif							/* not USE_LIBXML */
 }
 
@@ -4302,7 +4302,7 @@ xml_is_well_formed_document(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(wellformed_xml(data, XMLOPTION_DOCUMENT));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif							/* not USE_LIBXML */
 }
 
@@ -4315,7 +4315,7 @@ xml_is_well_formed_content(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(wellformed_xml(data, XMLOPTION_CONTENT));
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif							/* not USE_LIBXML */
 }
 
@@ -4604,7 +4604,7 @@ XmlTableGetValue(TableFuncScanState *state, int colnum,
 {
 #ifdef USE_LIBXML
 	XmlTableBuilderData *xtCxt;
-	Datum		result = (Datum) 0;
+	Datum		result = NullDatum;
 	xmlNodePtr	cur;
 	char	   *cstr = NULL;
 	volatile xmlXPathObjectPtr xpathobj = NULL;
@@ -4745,7 +4745,7 @@ XmlTableGetValue(TableFuncScanState *state, int colnum,
 	return result;
 #else
 	NO_XML_SUPPORT();
-	return 0;
+	return NullDatum;
 #endif							/* not USE_LIBXML */
 }
 
diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c
index aac5a2471d..2431f3751f 100644
--- a/src/backend/utils/cache/attoptcache.c
+++ b/src/backend/utils/cache/attoptcache.c
@@ -93,7 +93,7 @@ InitializeAttoptCache(void)
 	/* Watch for invalidation events. */
 	CacheRegisterSyscacheCallback(ATTNUM,
 								  InvalidateAttoptCacheCallback,
-								  (Datum) 0);
+								  NullDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 00def27881..b4d1ccd228 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -140,7 +140,7 @@ namehashfast(Datum datum)
 {
 	char	   *key = NameStr(*DatumGetName(datum));
 
-	return hash_any((unsigned char *) key, strlen(key));
+	return DatumGetUInt32(hash_any((unsigned char *) key, strlen(key)));
 }
 
 static bool
@@ -318,10 +318,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 = NullDatum,
+				v2 = NullDatum,
+				v3 = NullDatum,
+				v4 = NullDatum;
 	bool		isNull = false;
 	int		   *cc_keyno = cache->cc_keyno;
 	TupleDesc	cc_tupdesc = cache->cc_tupdesc;
@@ -1164,7 +1164,7 @@ HeapTuple
 SearchCatCache1(CatCache *cache,
 				Datum v1)
 {
-	return SearchCatCacheInternal(cache, 1, v1, 0, 0, 0);
+	return SearchCatCacheInternal(cache, 1, v1, NullDatum, NullDatum, NullDatum);
 }
 
 
@@ -1172,7 +1172,7 @@ HeapTuple
 SearchCatCache2(CatCache *cache,
 				Datum v1, Datum v2)
 {
-	return SearchCatCacheInternal(cache, 2, v1, v2, 0, 0);
+	return SearchCatCacheInternal(cache, 2, v1, v2, NullDatum, NullDatum);
 }
 
 
@@ -1180,7 +1180,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, NullDatum);
 }
 
 
@@ -1509,7 +1509,7 @@ SearchCatCacheList(CatCache *cache,
 				   Datum v2,
 				   Datum v3)
 {
-	Datum		v4 = 0;			/* dummy last-column value */
+	Datum		v4 = NullDatum;		/* dummy last-column value */
 	Datum		arguments[CATCACHE_MAXKEYS];
 	uint32		lHashValue;
 	dlist_iter	iter;
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index 419bde567b..9f5b366d08 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -108,7 +108,7 @@ BuildEventTriggerCache(void)
 								  ALLOCSET_DEFAULT_SIZES);
 		CacheRegisterSyscacheCallback(EVENTTRIGGEROID,
 									  InvalidateEventCacheCallback,
-									  (Datum) 0);
+									  NullDatum);
 	}
 
 	/* Switch to correct memory context. */
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index c13c08a97b..28ec64dadd 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -1904,7 +1904,7 @@ get_transform_fromsql(Oid typid, Oid langid, List *trftypes)
 	if (!list_member_oid(trftypes, typid))
 		return InvalidOid;
 
-	tup = SearchSysCache2(TRFTYPELANG, typid, langid);
+	tup = SearchSysCache2(TRFTYPELANG, ObjectIdGetDatum(typid), ObjectIdGetDatum(langid));
 	if (HeapTupleIsValid(tup))
 	{
 		Oid			funcid;
@@ -1925,7 +1925,7 @@ get_transform_tosql(Oid typid, Oid langid, List *trftypes)
 	if (!list_member_oid(trftypes, typid))
 		return InvalidOid;
 
-	tup = SearchSysCache2(TRFTYPELANG, typid, langid);
+	tup = SearchSysCache2(TRFTYPELANG, ObjectIdGetDatum(typid), ObjectIdGetDatum(langid));
 	if (HeapTupleIsValid(tup))
 	{
 		Oid			funcid;
diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c
index 342ab4dbaa..0fa6b92487 100644
--- a/src/backend/utils/cache/partcache.c
+++ b/src/backend/utils/cache/partcache.c
@@ -336,7 +336,7 @@ generate_partition_qual(Relation rel)
 						   AccessShareLock);
 
 	/* Get pg_class.relpartbound */
-	tuple = SearchSysCache1(RELOID, RelationGetRelid(rel));
+	tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(RelationGetRelid(rel)));
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "cache lookup failed for relation %u",
 			 RelationGetRelid(rel));
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index abc3062892..e63c9228f8 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -126,14 +126,14 @@ int			plan_cache_mode;
 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, NullDatum);
+	CacheRegisterSyscacheCallback(PROCOID, PlanCacheObjectCallback, NullDatum);
+	CacheRegisterSyscacheCallback(TYPEOID, PlanCacheObjectCallback, NullDatum);
+	CacheRegisterSyscacheCallback(NAMESPACEOID, PlanCacheSysCallback, NullDatum);
+	CacheRegisterSyscacheCallback(OPEROID, PlanCacheSysCallback, NullDatum);
+	CacheRegisterSyscacheCallback(AMOPOPID, PlanCacheSysCallback, NullDatum);
+	CacheRegisterSyscacheCallback(FOREIGNSERVEROID, PlanCacheSysCallback, NullDatum);
+	CacheRegisterSyscacheCallback(FOREIGNDATAWRAPPEROID, PlanCacheSysCallback, NullDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/relfilenodemap.c b/src/backend/utils/cache/relfilenodemap.c
index c506dc9dec..8802e118ee 100644
--- a/src/backend/utils/cache/relfilenodemap.c
+++ b/src/backend/utils/cache/relfilenodemap.c
@@ -128,7 +128,7 @@ InitializeRelfilenodeMap(void)
 
 	/* Watch for invalidation events. */
 	CacheRegisterRelcacheCallback(RelfilenodeMapInvalidateCallback,
-								  (Datum) 0);
+								  NullDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
index 6309a017c1..871038644b 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);
+								  NullDatum);
 }
 
 /*
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 16297a52a1..c3f53570f2 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -1244,9 +1244,9 @@ GetSysCacheOid(int cacheId,
 	tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
 	if (!HeapTupleIsValid(tuple))
 		return InvalidOid;
-	result = heap_getattr(tuple, oidcol,
+	result = DatumGetObjectId(heap_getattr(tuple, oidcol,
 						  SysCache[cacheId]->cc_tupdesc,
-						  &isNull);
+						  &isNull));
 	Assert(!isNull);			/* columns used as oids should never be NULL */
 	ReleaseSysCache(tuple);
 	return result;
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index fc01e7876d..0e2d750f36 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -336,10 +336,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(CLAOID, TypeCacheOpcCallback, (Datum) 0);
-		CacheRegisterSyscacheCallback(CONSTROID, TypeCacheConstrCallback, (Datum) 0);
-		CacheRegisterSyscacheCallback(TYPEOID, TypeCacheConstrCallback, (Datum) 0);
+		CacheRegisterRelcacheCallback(TypeCacheRelCallback, NullDatum);
+		CacheRegisterSyscacheCallback(CLAOID, TypeCacheOpcCallback, NullDatum);
+		CacheRegisterSyscacheCallback(CONSTROID, TypeCacheConstrCallback, NullDatum);
+		CacheRegisterSyscacheCallback(TYPEOID, TypeCacheConstrCallback, NullDatum);
 
 		/* Also make sure CacheMemoryContext exists */
 		if (!CacheMemoryContext)
@@ -1996,7 +1996,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, NullDatum);
 }
 
 /*
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 9b640ccd40..89e475b140 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -1534,7 +1534,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 NullDatum;		/* just return null result */
 
 	InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
 
@@ -1593,7 +1593,7 @@ ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
 	Datum		result;
 
 	if (buf == NULL && flinfo->fn_strict)
-		return (Datum) 0;		/* just return null result */
+		return NullDatum;		/* 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 b7fac5d295..8e138fbf6d 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -982,7 +982,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes,
 	int			i;
 
 	/* Do nothing if null proargnames */
-	if (proargnames == PointerGetDatum(NULL))
+	if (!DatumGetPointer(proargnames))
 	{
 		*arg_names = NULL;
 		return 0;
@@ -1000,7 +1000,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes,
 		elog(ERROR, "proargnames is not a 1-D text array");
 	deconstruct_array(arr, TEXTOID, -1, false, 'i',
 					  &argnames, NULL, &numargs);
-	if (proargmodes != PointerGetDatum(NULL))
+	if (DatumGetPointer(proargmodes))
 	{
 		arr = DatumGetArrayTypeP(proargmodes);	/* ensure not toasted */
 		if (ARR_NDIM(arr) != 1 ||
@@ -1226,8 +1226,7 @@ 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) || !DatumGetPointer(proargmodes))
 		return NULL;
 
 	/*
@@ -1250,7 +1249,7 @@ build_function_result_tupdesc_d(char prokind,
 		ARR_ELEMTYPE(arr) != CHAROID)
 		elog(ERROR, "proargmodes is not a 1-D char array");
 	argmodes = (char *) ARR_DATA_PTR(arr);
-	if (proargnames != PointerGetDatum(NULL))
+	if (DatumGetPointer(proargnames))
 	{
 		arr = DatumGetArrayTypeP(proargnames);	/* ensure not toasted */
 		if (ARR_NDIM(arr) != 1 ||
@@ -1531,7 +1530,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] = NullDatum;
 				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 83c9514856..ee8e831c43 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -1154,7 +1154,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, NullDatum);
 
 	/*
 	 * 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 43b9f17f72..28f48b6497 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -672,7 +672,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 		/* Reset CurrentResourceOwner to nothing for the moment */
 		CurrentResourceOwner = NULL;
 
-		on_shmem_exit(ShutdownXLOG, 0);
+		on_shmem_exit(ShutdownXLOG, NullDatum);
 	}
 
 	/*
@@ -706,7 +706,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 	 * transaction --- if we fail during the initialization transaction, as is
 	 * entirely possible, we need the AbortTransaction call to clean up.
 	 */
-	before_shmem_exit(ShutdownPostgres, 0);
+	before_shmem_exit(ShutdownPostgres, NullDatum);
 
 	/* The autovacuum launcher is done here */
 	if (IsAutoVacuumLauncherProcess())
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index fc463601ff..5172d92416 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -9547,7 +9547,7 @@ show_all_file_settings(PG_FUNCTION_ARGS)
 
 	tuplestore_donestoring(tupstore);
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 static char *
diff --git a/src/backend/utils/misc/pg_config.c b/src/backend/utils/misc/pg_config.c
index 2d178391ab..a560075979 100644
--- a/src/backend/utils/misc/pg_config.c
+++ b/src/backend/utils/misc/pg_config.c
@@ -98,5 +98,5 @@ pg_config(PG_FUNCTION_ARGS)
 	rsinfo->setDesc = tupdesc;
 	MemoryContextSwitchTo(oldcontext);
 
-	return (Datum) 0;
+	return NullDatum;
 }
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index 56360817d9..b2cd6c2eb5 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -85,7 +85,7 @@ superuser_arg(Oid roleid)
 	{
 		CacheRegisterSyscacheCallback(AUTHOID,
 									  RoleidCallback,
-									  (Datum) 0);
+									  NullDatum);
 		roleid_callback_registered = true;
 	}
 
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 334e35bb6a..e69b08a45d 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -1201,7 +1201,7 @@ pg_cursor(PG_FUNCTION_ARGS)
 	rsinfo->setResult = tupstore;
 	rsinfo->setDesc = tupdesc;
 
-	return (Datum) 0;
+	return NullDatum;
 }
 
 bool
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index 7be11c48ab..4fe8935347 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -243,7 +243,7 @@ ResourceArrayEnlarge(ResourceArray *resarr)
 		 */
 		for (i = 0; i < oldcap; i++)
 		{
-			if (olditemsarr[i] != resarr->invalidval)
+			if (olditemsarr[i].value != resarr->invalidval.value)
 				ResourceArrayAdd(resarr, olditemsarr[i]);
 		}
 
@@ -264,7 +264,7 @@ ResourceArrayAdd(ResourceArray *resarr, Datum value)
 {
 	uint32		idx;
 
-	Assert(value != resarr->invalidval);
+	Assert(value.value != resarr->invalidval.value);
 	Assert(resarr->nitems < resarr->maxitems);
 
 	if (RESARRAY_IS_ARRAY(resarr))
@@ -280,7 +280,7 @@ ResourceArrayAdd(ResourceArray *resarr, Datum value)
 		idx = DatumGetUInt32(hash_any((void *) &value, sizeof(value))) & mask;
 		for (;;)
 		{
-			if (resarr->itemsarr[idx] == resarr->invalidval)
+			if (resarr->itemsarr[idx].value == resarr->invalidval.value)
 				break;
 			idx = (idx + 1) & mask;
 		}
@@ -304,13 +304,13 @@ ResourceArrayRemove(ResourceArray *resarr, Datum value)
 				idx,
 				lastidx = resarr->lastidx;
 
-	Assert(value != resarr->invalidval);
+	Assert(value.value != resarr->invalidval.value);
 
 	/* Search through all items, but try lastidx first. */
 	if (RESARRAY_IS_ARRAY(resarr))
 	{
 		if (lastidx < resarr->nitems &&
-			resarr->itemsarr[lastidx] == value)
+			resarr->itemsarr[lastidx].value == value.value)
 		{
 			resarr->itemsarr[lastidx] = resarr->itemsarr[resarr->nitems - 1];
 			resarr->nitems--;
@@ -320,7 +320,7 @@ ResourceArrayRemove(ResourceArray *resarr, Datum value)
 		}
 		for (i = 0; i < resarr->nitems; i++)
 		{
-			if (resarr->itemsarr[i] == value)
+			if (resarr->itemsarr[i].value == value.value)
 			{
 				resarr->itemsarr[i] = resarr->itemsarr[resarr->nitems - 1];
 				resarr->nitems--;
@@ -335,7 +335,7 @@ ResourceArrayRemove(ResourceArray *resarr, Datum value)
 		uint32		mask = resarr->capacity - 1;
 
 		if (lastidx < resarr->capacity &&
-			resarr->itemsarr[lastidx] == value)
+			resarr->itemsarr[lastidx].value == value.value)
 		{
 			resarr->itemsarr[lastidx] = resarr->invalidval;
 			resarr->nitems--;
@@ -344,7 +344,7 @@ ResourceArrayRemove(ResourceArray *resarr, Datum value)
 		idx = DatumGetUInt32(hash_any((void *) &value, sizeof(value))) & mask;
 		for (i = 0; i < resarr->capacity; i++)
 		{
-			if (resarr->itemsarr[idx] == value)
+			if (resarr->itemsarr[idx].value == value.value)
 			{
 				resarr->itemsarr[idx] = resarr->invalidval;
 				resarr->nitems--;
@@ -385,7 +385,7 @@ ResourceArrayGetAny(ResourceArray *resarr, Datum *value)
 		for (;;)
 		{
 			resarr->lastidx &= mask;
-			if (resarr->itemsarr[resarr->lastidx] != resarr->invalidval)
+			if (resarr->itemsarr[resarr->lastidx].value != resarr->invalidval.value)
 				break;
 			resarr->lastidx++;
 		}
@@ -549,7 +549,7 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
 		/* Ditto for JIT contexts */
 		while (ResourceArrayGetAny(&(owner->jitarr), &foundres))
 		{
-			JitContext *context = (JitContext *) PointerGetDatum(foundres);
+			JitContext *context = (JitContext *) DatumGetPointer(foundres);
 
 			jit_release_context(context);
 		}
@@ -842,7 +842,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, NullDatum);
 
 }
 
diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c
index 9a771214dc..ade5fc56a6 100644
--- a/src/backend/utils/sort/sortsupport.c
+++ b/src/backend/utils/sort/sortsupport.c
@@ -57,7 +57,7 @@ comparison_shim(Datum x, Datum y, SortSupport ssup)
 	if (extra->fcinfo.isnull)
 		elog(ERROR, "function %u returned NULL", extra->flinfo.fn_oid);
 
-	return result;
+	return DatumGetInt32(result);
 }
 
 /*
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 7b8e67899e..04a01203fc 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -1575,7 +1575,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 : NullDatum;
 		stup.isnull1 = isNull;
 		stup.tuple = NULL;		/* no separate storage */
 		MemoryContextSwitchTo(state->sortcontext);
@@ -4328,7 +4328,7 @@ readtup_datum(Tuplesortstate *state, SortTuple *stup,
 	if (tuplen == 0)
 	{
 		/* it's NULL */
-		stup->datum1 = (Datum) 0;
+		stup->datum1 = NullDatum;
 		stup->isnull1 = true;
 		stup->tuple = NULL;
 	}
diff --git a/src/include/access/gin.h b/src/include/access/gin.h
index a8eef5a379..0d653bf5de 100644
--- a/src/include/access/gin.h
+++ b/src/include/access/gin.h
@@ -61,8 +61,8 @@ typedef char GinTernaryValue;
 #define GIN_MAYBE		2		/* don't know if item is present / don't know
 								 * if matches */
 
-#define DatumGetGinTernaryValue(X) ((GinTernaryValue)(X))
-#define GinTernaryValueGetDatum(X) ((Datum)(X))
+#define DatumGetGinTernaryValue(X) (DatumGetInt32(X))
+#define GinTernaryValueGetDatum(X) (Int32GetDatum(X))
 #define PG_RETURN_GIN_TERNARY_VALUE(x) return GinTernaryValueGetDatum(x)
 
 /* GUC parameters */
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index 27f963e9e8..985845dfa2 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -729,7 +729,7 @@ struct MinimalTupleData
 		att_isnull((attnum)-1, (tup)->t_data->t_bits) ?				\
 		(															\
 			(*(isnull) = true),										\
-			(Datum)NULL												\
+			NullDatum												\
 		)															\
 		:															\
 		(															\
diff --git a/src/include/access/itup.h b/src/include/access/itup.h
index 744ffb6c61..9085c1b7ad 100644
--- a/src/include/access/itup.h
+++ b/src/include/access/itup.h
@@ -117,7 +117,7 @@ typedef IndexAttributeBitMapData * IndexAttributeBitMap;
 		(att_isnull((attnum)-1, (char *)(tup) + sizeof(IndexTupleData))) ? \
 		( \
 			*(isnull) = true, \
-			(Datum)NULL \
+			NullDatum \
 		) \
 		: \
 		( \
diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h
index 4a38938732..c1aa56c2a8 100644
--- a/src/include/access/spgist_private.h
+++ b/src/include/access/spgist_private.h
@@ -269,7 +269,7 @@ typedef SpGistInnerTupleData *SpGistInnerTuple;
 							 ((s)->attPrefixType.attbyval ? \
 							  *(Datum *) _SGITDATA(x) : \
 							  PointerGetDatum(_SGITDATA(x))) \
-							 : (Datum) 0)
+							 : NullDatum)
 #define SGITNODEPTR(x)		((SpGistNodeTuple) (_SGITDATA(x) + (x)->prefixSize))
 
 /* Macro for iterating through the nodes of an inner tuple */
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 3ff099986b..2eff436e7f 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -333,10 +333,10 @@ 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 NullDatum; } while (0)
 
 /* A few internal functions return void (which is not the same as NULL!) */
-#define PG_RETURN_VOID()	 return (Datum) 0
+#define PG_RETURN_VOID()	 return NullDatum
 
 /* Macros for returning results of standard types */
 
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 4e2fb39105..6f9a0c02de 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -609,7 +609,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 *bmsToString(const struct Bitmapset *bms);
@@ -622,7 +622,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/postgres.h b/src/include/postgres.h
index 057a3413ac..1625aa47a5 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -364,7 +364,22 @@ typedef struct
  * convert between a Datum and the appropriate C type.
  */
 
-typedef uintptr_t Datum;
+//typedef uintptr_t Datum;
+
+#ifndef PG_DATUM_DEFINED
+#define PG_DATUM_DEFINED
+typedef struct Datum
+{
+	uintptr_t value;
+} Datum;
+#endif
+
+static inline Datum MakeDatum(uintptr_t value)
+{
+	Datum v;
+	v.value = value;
+	return v;
+}
 
 /*
  * A NullableDatum is used in places where both a Datum and its nullness needs
@@ -390,7 +405,7 @@ typedef struct NullableDatum
  * Note: any nonzero value will be considered true.
  */
 
-#define DatumGetBool(X) ((bool) ((X) != 0))
+#define DatumGetBool(X) ((bool) ((X).value != 0))
 
 /*
  * BoolGetDatum
@@ -399,161 +414,163 @@ typedef struct NullableDatum
  * Note: any nonzero value will be considered true.
  */
 
-#define BoolGetDatum(X) ((Datum) ((X) ? 1 : 0))
+#define BoolGetDatum(X) (MakeDatum((X) ? 1 : 0))
 
 /*
  * DatumGetChar
  *		Returns character value of a datum.
  */
 
-#define DatumGetChar(X) ((char) (X))
+#define DatumGetChar(X) ((char) (X).value)
 
 /*
  * CharGetDatum
  *		Returns datum representation for a character.
  */
 
-#define CharGetDatum(X) ((Datum) (X))
+#define CharGetDatum(X) (MakeDatum(X))
 
 /*
  * Int8GetDatum
  *		Returns datum representation for an 8-bit integer.
  */
 
-#define Int8GetDatum(X) ((Datum) (X))
+#define Int8GetDatum(X) ((Datum) (X).value)
 
 /*
  * DatumGetUInt8
  *		Returns 8-bit unsigned integer value of a datum.
  */
 
-#define DatumGetUInt8(X) ((uint8) (X))
+#define DatumGetUInt8(X) ((uint8) (X).value)
 
 /*
  * UInt8GetDatum
  *		Returns datum representation for an 8-bit unsigned integer.
  */
 
-#define UInt8GetDatum(X) ((Datum) (X))
+#define UInt8GetDatum(X) ((Datum) (X).value)
 
 /*
  * DatumGetInt16
  *		Returns 16-bit integer value of a datum.
  */
 
-#define DatumGetInt16(X) ((int16) (X))
+#define DatumGetInt16(X) ((int16) (X).value)
 
 /*
  * Int16GetDatum
  *		Returns datum representation for a 16-bit integer.
  */
 
-#define Int16GetDatum(X) ((Datum) (X))
+#define Int16GetDatum(X) (MakeDatum(X))
 
 /*
  * DatumGetUInt16
  *		Returns 16-bit unsigned integer value of a datum.
  */
 
-#define DatumGetUInt16(X) ((uint16) (X))
+#define DatumGetUInt16(X) ((uint16) (X).value)
 
 /*
  * UInt16GetDatum
  *		Returns datum representation for a 16-bit unsigned integer.
  */
 
-#define UInt16GetDatum(X) ((Datum) (X))
+#define UInt16GetDatum(X) (MakeDatum(X))
 
 /*
  * DatumGetInt32
  *		Returns 32-bit integer value of a datum.
  */
 
-#define DatumGetInt32(X) ((int32) (X))
+#define DatumGetInt32(X) ((int32) (X).value)
 
 /*
  * Int32GetDatum
  *		Returns datum representation for a 32-bit integer.
  */
 
-#define Int32GetDatum(X) ((Datum) (X))
+#define Int32GetDatum(X) (MakeDatum(X))
 
 /*
  * DatumGetUInt32
  *		Returns 32-bit unsigned integer value of a datum.
  */
 
-#define DatumGetUInt32(X) ((uint32) (X))
+#define DatumGetUInt32(X) ((uint32) (X).value)
 
 /*
  * UInt32GetDatum
  *		Returns datum representation for a 32-bit unsigned integer.
  */
 
-#define UInt32GetDatum(X) ((Datum) (X))
+#define UInt32GetDatum(X) (MakeDatum(X))
 
 /*
  * DatumGetObjectId
  *		Returns object identifier value of a datum.
  */
 
-#define DatumGetObjectId(X) ((Oid) (X))
+#define DatumGetObjectId(X) ((Oid) (X).value)
 
 /*
  * ObjectIdGetDatum
  *		Returns datum representation for an object identifier.
  */
 
-#define ObjectIdGetDatum(X) ((Datum) (X))
+#define ObjectIdGetDatum(X) (MakeDatum(X))
 
 /*
  * DatumGetTransactionId
  *		Returns transaction identifier value of a datum.
  */
 
-#define DatumGetTransactionId(X) ((TransactionId) (X))
+#define DatumGetTransactionId(X) ((TransactionId) (X).value)
 
 /*
  * TransactionIdGetDatum
  *		Returns datum representation for a transaction identifier.
  */
 
-#define TransactionIdGetDatum(X) ((Datum) (X))
+#define TransactionIdGetDatum(X) (MakeDatum(X))
 
 /*
  * MultiXactIdGetDatum
  *		Returns datum representation for a multixact identifier.
  */
 
-#define MultiXactIdGetDatum(X) ((Datum) (X))
+#define MultiXactIdGetDatum(X) (MakeDatum(X))
 
 /*
  * DatumGetCommandId
  *		Returns command identifier value of a datum.
  */
 
-#define DatumGetCommandId(X) ((CommandId) (X))
+#define DatumGetCommandId(X) ((CommandId) (X).value)
 
 /*
  * CommandIdGetDatum
  *		Returns datum representation for a command identifier.
  */
 
-#define CommandIdGetDatum(X) ((Datum) (X))
+#define CommandIdGetDatum(X) (MakeDatum(X))
 
 /*
  * DatumGetPointer
  *		Returns pointer value of a datum.
  */
 
-#define DatumGetPointer(X) ((Pointer) (X))
+#define DatumGetPointer(X) ((Pointer) (X).value)
 
 /*
  * PointerGetDatum
  *		Returns datum representation for a pointer.
  */
 
-#define PointerGetDatum(X) ((Datum) (X))
+#define PointerGetDatum(X) (MakeDatum((uint64_t) (X)))
+
+#define NullDatum PointerGetDatum(NULL)
 
 /*
  * DatumGetCString
@@ -602,7 +619,7 @@ typedef struct NullableDatum
  */
 
 #ifdef USE_FLOAT8_BYVAL
-#define DatumGetInt64(X) ((int64) (X))
+#define DatumGetInt64(X) ((int64) (X).value)
 #else
 #define DatumGetInt64(X) (* ((int64 *) DatumGetPointer(X)))
 #endif
@@ -616,7 +633,7 @@ typedef struct NullableDatum
  */
 
 #ifdef USE_FLOAT8_BYVAL
-#define Int64GetDatum(X) ((Datum) (X))
+#define Int64GetDatum(X) (MakeDatum(X))
 #else
 extern Datum Int64GetDatum(int64 X);
 #endif
@@ -629,7 +646,7 @@ extern Datum Int64GetDatum(int64 X);
  */
 
 #ifdef USE_FLOAT8_BYVAL
-#define DatumGetUInt64(X) ((uint64) (X))
+#define DatumGetUInt64(X) ((uint64) (X).value)
 #else
 #define DatumGetUInt64(X) (* ((uint64 *) DatumGetPointer(X)))
 #endif
@@ -643,9 +660,9 @@ extern Datum Int64GetDatum(int64 X);
  */
 
 #ifdef USE_FLOAT8_BYVAL
-#define UInt64GetDatum(X) ((Datum) (X))
+#define UInt64GetDatum(X) (MakeDatum(X))
 #else
-#define UInt64GetDatum(X) Int64GetDatum((int64) (X))
+#define UInt64GetDatum(X) Int64GetDatum((int64) (X).value)
 #endif
 
 /*
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index fdb61b7cf5..26cfa3c67d 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -24,6 +24,7 @@
 #define POSTGRES_EXT_H
 
 #include "pg_config_ext.h"
+#include <stdint.h>
 
 /*
  * Object ID is a fundamental type in Postgres.
@@ -46,6 +47,14 @@ typedef unsigned int Oid;
 /* Define a signed 64-bit integer type for use in client API declarations. */
 typedef PG_INT64_TYPE pg_int64;
 
+/* TODO: bleugh */
+#ifndef PG_DATUM_DEFINED
+#define PG_DATUM_DEFINED
+typedef struct Datum
+{
+	uintptr_t value;
+} Datum;
+#endif
 
 /*
  * Identifiers of error message fields.  Kept here to keep common
diff --git a/src/include/utils/arrayaccess.h b/src/include/utils/arrayaccess.h
index 47e74260d8..f86b7c4667 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 = NullDatum;
 		}
 		else
 		{
diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h
index 40ad5fda92..66afe4a341 100644
--- a/src/include/utils/jsonpath.h
+++ b/src/include/utils/jsonpath.h
@@ -29,8 +29,8 @@ typedef struct
 #define JSONPATH_LAX		(0x80000000)
 #define JSONPATH_HDRSZ		(offsetof(JsonPath, data))
 
-#define DatumGetJsonPathP(d)			((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM(d)))
-#define DatumGetJsonPathPCopy(d)		((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM_COPY(d)))
+#define DatumGetJsonPathP(d)			((JsonPath *) PG_DETOAST_DATUM(d))
+#define DatumGetJsonPathPCopy(d)		((JsonPath *) PG_DETOAST_DATUM_COPY(d))
 #define PG_GETARG_JSONPATH_P(x)			DatumGetJsonPathP(PG_GETARG_DATUM(x))
 #define PG_GETARG_JSONPATH_P_COPY(x)	DatumGetJsonPathPCopy(PG_GETARG_DATUM(x))
 #define PG_RETURN_JSONPATH_P(p)			PG_RETURN_POINTER(p)
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 918765cc99..d9f79ddb98 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -172,45 +172,45 @@ extern bool RelationSupportsSysCache(Oid relid);
  * maximum number of keys.
  */
 #define SearchSysCacheCopy1(cacheId, key1) \
-	SearchSysCacheCopy(cacheId, key1, 0, 0, 0)
+	SearchSysCacheCopy(cacheId, key1, NullDatum, NullDatum, NullDatum)
 #define SearchSysCacheCopy2(cacheId, key1, key2) \
-	SearchSysCacheCopy(cacheId, key1, key2, 0, 0)
+	SearchSysCacheCopy(cacheId, key1, key2, NullDatum, NullDatum)
 #define SearchSysCacheCopy3(cacheId, key1, key2, key3) \
-	SearchSysCacheCopy(cacheId, key1, key2, key3, 0)
+	SearchSysCacheCopy(cacheId, key1, key2, key3, NullDatum)
 #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, NullDatum, NullDatum, NullDatum)
 #define SearchSysCacheExists2(cacheId, key1, key2) \
-	SearchSysCacheExists(cacheId, key1, key2, 0, 0)
+	SearchSysCacheExists(cacheId, key1, key2, NullDatum, NullDatum)
 #define SearchSysCacheExists3(cacheId, key1, key2, key3) \
-	SearchSysCacheExists(cacheId, key1, key2, key3, 0)
+	SearchSysCacheExists(cacheId, key1, key2, key3, NullDatum)
 #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, NullDatum, NullDatum, NullDatum)
 #define GetSysCacheOid2(cacheId, oidcol, key1, key2) \
-	GetSysCacheOid(cacheId, oidcol, key1, key2, 0, 0)
+	GetSysCacheOid(cacheId, oidcol, key1, key2, NullDatum, NullDatum)
 #define GetSysCacheOid3(cacheId, oidcol, key1, key2, key3) \
-	GetSysCacheOid(cacheId, oidcol, key1, key2, key3, 0)
+	GetSysCacheOid(cacheId, oidcol, key1, key2, key3, NullDatum)
 #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, NullDatum, NullDatum, NullDatum)
 #define GetSysCacheHashValue2(cacheId, key1, key2) \
-	GetSysCacheHashValue(cacheId, key1, key2, 0, 0)
+	GetSysCacheHashValue(cacheId, key1, key2, NullDatum, NullDatum)
 #define GetSysCacheHashValue3(cacheId, key1, key2, key3) \
-	GetSysCacheHashValue(cacheId, key1, key2, key3, 0)
+	GetSysCacheHashValue(cacheId, key1, key2, key3, NullDatum)
 #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, NullDatum, NullDatum)
 #define SearchSysCacheList2(cacheId, key1, key2) \
-	SearchSysCacheList(cacheId, 2, key1, key2, 0)
+	SearchSysCacheList(cacheId, 2, key1, key2, NullDatum)
 #define SearchSysCacheList3(cacheId, key1, key2, key3) \
 	SearchSysCacheList(cacheId, 3, key1, key2, key3)
 
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 30c7e967df..2f43623bac 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1828,7 +1828,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 = NullDatum;
 				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 f5fdf93d0a..3547a0ef95 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -624,7 +624,7 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
 			rsi->setDesc = CreateTupleDescCopy(estate.tuple_store_desc);
 			MemoryContextSwitchTo(oldcxt);
 		}
-		estate.retval = (Datum) 0;
+		estate.retval = NullDatum;
 		fcinfo->isnull = true;
 	}
 	else if (!estate.retisnull)
@@ -965,7 +965,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,
+													   NullDatum,
 													   true,	/* isnull */
 													   false, false);
 		}
@@ -1461,7 +1461,7 @@ plpgsql_fulfill_promise(PLpgSQL_execstate *estate,
 			}
 			else
 			{
-				assign_simple_var(estate, var, (Datum) 0, true, false);
+				assign_simple_var(estate, var, NullDatum, true, false);
 			}
 			break;
 
@@ -1607,7 +1607,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, NullDatum, true, false);
 
 					if (var->default_val == NULL)
 					{
@@ -1620,7 +1620,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,
+											  NullDatum,
 											  true,
 											  UNKNOWNOID,
 											  -1);
@@ -2547,7 +2547,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, NullDatum, true, false);
 
 			/* Evaluate the statement(s), and we're done */
 			return exec_stmts(estate, cwt->stmts);
@@ -2556,7 +2556,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, NullDatum, true, false);
 
 	/* SQL2003 mandates this error if there was no ELSE clause */
 	if (!stmt->have_else)
@@ -2922,7 +2922,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, NullDatum, true, false);
 
 	return rc;
 }
@@ -3137,7 +3137,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 = NullDatum;
 	estate->retisnull = true;
 	estate->rettype = InvalidOid;
 
@@ -3254,7 +3254,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 = NullDatum;
 		estate->retisnull = false;
 		estate->rettype = VOIDOID;
 	}
@@ -3884,7 +3884,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
 	estate->trigdata = NULL;
 	estate->evtrigdata = NULL;
 
-	estate->retval = (Datum) 0;
+	estate->retval = NullDatum;
 	estate->retisnull = true;
 	estate->rettype = InvalidOid;
 
@@ -5027,7 +5027,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
@@ -5427,7 +5427,7 @@ exec_eval_datum(PLpgSQL_execstate *estate,
 				if (rec->erh == NULL)
 				{
 					/* Treat uninstantiated record as a simple NULL */
-					*value = (Datum) 0;
+					*value = NullDatum;
 					*isnull = true;
 					/* Report variable's declared type */
 					*typeid = rec->rectypeid;
@@ -5438,7 +5438,7 @@ exec_eval_datum(PLpgSQL_execstate *estate,
 					if (ExpandedRecordIsEmpty(rec->erh))
 					{
 						/* Empty record is also a NULL */
-						*value = (Datum) 0;
+						*value = NullDatum;
 						*isnull = true;
 					}
 					else
@@ -5753,7 +5753,7 @@ exec_eval_expr(PLpgSQL_execstate *estate,
 			   Oid *rettype,
 			   int32 *rettypmod)
 {
-	Datum		result = 0;
+	Datum		result = NullDatum;
 	int			rc;
 	Form_pg_attribute attr;
 
@@ -5805,7 +5805,7 @@ exec_eval_expr(PLpgSQL_execstate *estate,
 	if (estate->eval_processed == 0)
 	{
 		*isNull = true;
-		return (Datum) 0;
+		return NullDatum;
 	}
 
 	/*
@@ -6362,7 +6362,7 @@ plpgsql_param_fetch(ParamListInfo params,
 	/* Return "no such parameter" if not ok */
 	if (!ok)
 	{
-		prm->value = (Datum) 0;
+		prm->value = NullDatum;
 		prm->isnull = true;
 		prm->pflags = 0;
 		prm->ptype = InvalidOid;
@@ -7009,7 +7009,7 @@ exec_move_row_from_fields(PLpgSQL_execstate *estate,
 				else
 				{
 					/* no source for destination column */
-					value = (Datum) 0;
+					value = NullDatum;
 					isnull = true;
 					valtype = UNKNOWNOID;
 					valtypmod = -1;
@@ -7118,7 +7118,7 @@ exec_move_row_from_fields(PLpgSQL_execstate *estate,
 			else
 			{
 				/* no source for destination column */
-				value = (Datum) 0;
+				value = NullDatum;
 				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 ce03f1ef84..ab4a81eb64 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -261,7 +261,7 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
 		{
 			plpgsql_exec_event_trigger(func,
 									   (EventTriggerData *) fcinfo->context);
-			retval = (Datum) 0;
+			retval = NullDatum;
 		}
 		else
 			retval = plpgsql_exec_function(func, fcinfo, NULL, !nonatomic);
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index 7f03b7e857..484034586a 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -318,19 +318,19 @@ ttdummy(PG_FUNCTION_ARGS)
 		if (isnull)
 			elog(ERROR, "ttdummy (%s): %s must be NOT NULL", relname, args[1]);
 
-		if (oldon != newon || oldoff != newoff)
+		if (oldon.value != newon.value || oldoff.value != newoff.value)
 			ereport(ERROR,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("ttdummy (%s): you cannot change %s and/or %s columns (use set_ttdummy)",
 							relname, args[0], args[1])));
 
-		if (newoff != TTDUMMY_INFINITY)
+		if (newoff.value != TTDUMMY_INFINITY)
 		{
 			pfree(relname);		/* allocated in upper executor context */
 			return PointerGetDatum(NULL);
 		}
 	}
-	else if (oldoff != TTDUMMY_INFINITY)	/* DELETE */
+	else if (oldoff.value != TTDUMMY_INFINITY)	/* DELETE */
 	{
 		pfree(relname);
 		return PointerGetDatum(NULL);
@@ -359,7 +359,7 @@ ttdummy(PG_FUNCTION_ARGS)
 	{
 		cvals[attnum[0] - 1] = newoff;	/* start_date eq current date */
 		cnulls[attnum[0] - 1] = ' ';
-		cvals[attnum[1] - 1] = TTDUMMY_INFINITY;	/* stop_date eq INFINITY */
+		cvals[attnum[1] - 1] = Int32GetDatum(TTDUMMY_INFINITY);	/* stop_date eq INFINITY */
 		cnulls[attnum[1] - 1] = ' ';
 	}
 	else
-- 
2.22.0

#2Corey Huinker
corey.huinker@gmail.com
In reply to: Thomas Munro (#1)
Re: Catching missing Datum conversions

I should probably split this into "actionable" (categories 3 and 4)
and "noise and scaffolding" patches.

Breaking down the noise-and-scaffolding into some subgroups might make the
rather long patches more palatable/exceedingly-obvious:
* (Datum) 0 ---> NullDatum
* 0 ----> NullDatum
* The DatumGetPointer(allParameterTypes) null tests

Having said that, everything you did seems really straightforward, except
for

src/backend/rewrite/rewriteDefine.c
src/backend/statistics/mcv.c
src/backend/tsearch/ts_parse.c

and those seem like cases where the DatumGetXXX was a no-op before Datum
was a struct.

#3Robert Haas
robertmhaas@gmail.com
In reply to: Thomas Munro (#1)
Re: Catching missing Datum conversions

On Fri, Jul 19, 2019 at 7:55 PM Thomas Munro <thomas.munro@gmail.com> wrote:

When reviewing a recent patch, I missed a place where Datum was being
converted to another type implicitly (ie without going though a
DatumGetXXX() macro). Thanks to Jeff for fixing that (commit
b538c90b), but I was curious to see if I could convince my compiler to
tell me about that sort of thing.

This is a very easy mistake to make, so if you ever feel like
returning to this topic in earnest, I think it could be a worthwhile
expenditure of time.

--
Robert Haas
EDB: http://www.enterprisedb.com