diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index bb83a9a7c6e52a894f287678a3ad1eabec91c75c..6ab849c6ef5eb36174ab0686c431b9ca8ef0fcac 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -930,7 +930,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
 			querytree_list = NIL;
 			foreach(lc, raw_parsetree_list)
 			{
-				RawStmt    *parsetree = (RawStmt *) lfirst(lc);
+				RawStmt    *parsetree = castNode(RawStmt, lfirst(lc));
 				List	   *querytree_sublist;
 
 				querytree_sublist = pg_analyze_and_rewrite_params(parsetree,
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 02cfcd182d01a0c728257156d5fd9d28f296afb5..646a88409f2c374cb4b0357e72d6d7dac6b594fb 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -322,7 +322,7 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
 			elog(ERROR, "unexpected rewrite result for %s",
 				 is_matview ? "CREATE MATERIALIZED VIEW" :
 				 "CREATE TABLE AS SELECT");
-		query = (Query *) linitial(rewritten);
+		query = castNode(Query, linitial(rewritten));
 		Assert(query->commandType == CMD_SELECT);
 
 		/* plan the query --- note we disallow parallelism */
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 5d61a0195ed82dcbcaf2c0e22b76514c87c71429..0a67be031be8e9ef40d735cc702e8ccc83af3ff2 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -224,8 +224,7 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
 	 * executed repeatedly.  (See also the same hack in DECLARE CURSOR and
 	 * PREPARE.)  XXX FIXME someday.
 	 */
-	Assert(IsA(stmt->query, Query));
-	rewritten = QueryRewrite((Query *) copyObject(stmt->query));
+	rewritten = QueryRewrite(castNode(Query, copyObject(stmt->query)));
 
 	/* emit opening boilerplate */
 	ExplainBeginOutput(es);
@@ -246,7 +245,7 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
 		/* Explain every plan */
 		foreach(l, rewritten)
 		{
-			ExplainOneQuery((Query *) lfirst(l),
+			ExplainOneQuery(castNode(Query, lfirst(l)),
 							CURSOR_OPT_PARALLEL_OK, NULL, es,
 							queryString, params);
 
@@ -395,10 +394,9 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
 		CreateTableAsStmt *ctas = (CreateTableAsStmt *) utilityStmt;
 		List	   *rewritten;
 
-		Assert(IsA(ctas->query, Query));
-		rewritten = QueryRewrite((Query *) copyObject(ctas->query));
+		rewritten = QueryRewrite(castNode(Query, copyObject(ctas->query)));
 		Assert(list_length(rewritten) == 1);
-		ExplainOneQuery((Query *) linitial(rewritten),
+		ExplainOneQuery(castNode(Query, linitial(rewritten)),
 						0, ctas->into, es,
 						queryString, params);
 	}
@@ -415,10 +413,9 @@ ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es,
 		DeclareCursorStmt *dcs = (DeclareCursorStmt *) utilityStmt;
 		List	   *rewritten;
 
-		Assert(IsA(dcs->query, Query));
-		rewritten = QueryRewrite((Query *) copyObject(dcs->query));
+		rewritten = QueryRewrite(castNode(Query, copyObject(dcs->query)));
 		Assert(list_length(rewritten) == 1);
-		ExplainOneQuery((Query *) linitial(rewritten),
+		ExplainOneQuery(castNode(Query, linitial(rewritten)),
 						dcs->options, NULL, es,
 						queryString, params);
 	}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 554fdc46b41bec45a39d6ef004ffde1e03376c9a..9680d986a014e4ee39c67ddaeec775616743d5a8 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -713,7 +713,7 @@ execute_sql_string(const char *sql, const char *filename)
 	 */
 	foreach(lc1, raw_parsetree_list)
 	{
-		RawStmt    *parsetree = (RawStmt *) lfirst(lc1);
+		RawStmt    *parsetree = castNode(RawStmt, lfirst(lc1));
 		List	   *stmt_list;
 		ListCell   *lc2;
 
@@ -725,7 +725,7 @@ execute_sql_string(const char *sql, const char *filename)
 
 		foreach(lc2, stmt_list)
 		{
-			PlannedStmt *stmt = (PlannedStmt *) lfirst(lc2);
+			PlannedStmt *stmt = castNode(PlannedStmt, lfirst(lc2));
 
 			CommandCounterIncrement();
 
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index 476a023ec54c91f4eec31a8b7c54692d4ff97f26..6ff8b6998be8206e9c5645cb3a1feeeaeb8332eb 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -1572,7 +1572,7 @@ ImportForeignSchema(ImportForeignSchemaStmt *stmt)
 		 */
 		foreach(lc2, raw_parsetree_list)
 		{
-			RawStmt    *rs = (RawStmt *) lfirst(lc2);
+			RawStmt    *rs = castNode(RawStmt, lfirst(lc2));
 			CreateForeignTableStmt *cstmt = (CreateForeignTableStmt *) rs->stmt;
 			PlannedStmt *pstmt;
 
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index 1d3e39299b9d405751a96286b6c22201e48a129d..29d0430dd876ae4c7ad5c7de9433350697ea3775 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -42,14 +42,12 @@ void
 PerformCursorOpen(DeclareCursorStmt *cstmt, ParamListInfo params,
 				  const char *queryString, bool isTopLevel)
 {
-	Query	   *query = (Query *) cstmt->query;
+	Query	   *query = castNode(Query, cstmt->query);
 	List	   *rewritten;
 	PlannedStmt *plan;
 	Portal		portal;
 	MemoryContext oldContext;
 
-	Assert(IsA(query, Query));	/* else parse analysis wasn't done */
-
 	/*
 	 * Disallow empty-string cursor name (conflicts with protocol-level
 	 * unnamed portal).
@@ -85,7 +83,7 @@ PerformCursorOpen(DeclareCursorStmt *cstmt, ParamListInfo params,
 	if (list_length(rewritten) != 1)
 		elog(ERROR, "non-SELECT statement in DECLARE CURSOR");
 
-	query = (Query *) linitial(rewritten);
+	query = castNode(Query, linitial(rewritten));
 
 	if (query->commandType != CMD_SELECT)
 		elog(ERROR, "non-SELECT statement in DECLARE CURSOR");
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 7d7e3daf1e7c008405e188b9c1de5a7a18366866..7b61da3ef00c61560fce3732d3c10518313e1eca 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -265,8 +265,7 @@ ExecuteQuery(ExecuteStmt *stmt, IntoClause *intoClause,
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 					 errmsg("prepared statement is not a SELECT")));
-		pstmt = (PlannedStmt *) linitial(plan_list);
-		Assert(IsA(pstmt, PlannedStmt));
+		pstmt = castNode(PlannedStmt, linitial(plan_list));
 		if (pstmt->commandType != CMD_SELECT)
 			ereport(ERROR,
 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -670,9 +669,8 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
 	/* Explain each query */
 	foreach(p, plan_list)
 	{
-		PlannedStmt *pstmt = (PlannedStmt *) lfirst(p);
+		PlannedStmt *pstmt = castNode(PlannedStmt, lfirst(p));
 
-		Assert(IsA(pstmt, PlannedStmt));
 		if (pstmt->commandType != CMD_UTILITY)
 			ExplainOnePlan(pstmt, into, es, query_string, paramLI, NULL);
 		else
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 04b5d9a943ca5e93c55120d106a86dc6aaff0adb..90f2f7f00e2aa6c9d917689a6cd2bc797fc8ea02 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9281,7 +9281,7 @@ ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
 	querytree_list = NIL;
 	foreach(list_item, raw_parsetree_list)
 	{
-		RawStmt    *rs = (RawStmt *) lfirst(list_item);
+		RawStmt    *rs = castNode(RawStmt, lfirst(list_item));
 		Node	   *stmt = rs->stmt;
 
 		if (IsA(stmt, IndexStmt))
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 15c709139add17d1a733b38ca345effcfbc82ac0..2d49a65650279b921f119b7545c38d0ead5b30f3 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -707,7 +707,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
 	flat_query_list = NIL;
 	foreach(lc, raw_parsetree_list)
 	{
-		RawStmt    *parsetree = (RawStmt *) lfirst(lc);
+		RawStmt    *parsetree = castNode(RawStmt, lfirst(lc));
 		List	   *queryTree_sublist;
 
 		queryTree_sublist = pg_analyze_and_rewrite_params(parsetree,
@@ -1551,7 +1551,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 	parse = NULL;
 	foreach(lc, queryTreeList)
 	{
-		Query	   *q = (Query *) lfirst(lc);
+		Query	   *q = castNode(Query, lfirst(lc));
 
 		if (q->canSetTag)
 			parse = q;
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 7bd37283b7f809560ed314078dabc4838520038c..55f97b14e6e546279ff67152834c4944e88b0cde 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1232,9 +1232,9 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
 	if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
 	{
 		if (list_length(stmt_list) == 1 &&
-		 ((PlannedStmt *) linitial(stmt_list))->commandType != CMD_UTILITY &&
-			((PlannedStmt *) linitial(stmt_list))->rowMarks == NIL &&
-			ExecSupportsBackwardScan(((PlannedStmt *) linitial(stmt_list))->planTree))
+			castNode(PlannedStmt, linitial(stmt_list))->commandType != CMD_UTILITY &&
+			castNode(PlannedStmt, linitial(stmt_list))->rowMarks == NIL &&
+			ExecSupportsBackwardScan(castNode(PlannedStmt, linitial(stmt_list))->planTree))
 			portal->cursorOptions |= CURSOR_OPT_SCROLL;
 		else
 			portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
@@ -1248,8 +1248,8 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
 	if (portal->cursorOptions & CURSOR_OPT_SCROLL)
 	{
 		if (list_length(stmt_list) == 1 &&
-		 ((PlannedStmt *) linitial(stmt_list))->commandType != CMD_UTILITY &&
-			((PlannedStmt *) linitial(stmt_list))->rowMarks != NIL)
+			castNode(PlannedStmt, linitial(stmt_list))->commandType != CMD_UTILITY &&
+			castNode(PlannedStmt, linitial(stmt_list))->rowMarks != NIL)
 			ereport(ERROR,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
@@ -1270,7 +1270,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
 
 		foreach(lc, stmt_list)
 		{
-			PlannedStmt *pstmt = (PlannedStmt *) lfirst(lc);
+			PlannedStmt *pstmt = castNode(PlannedStmt, lfirst(lc));
 
 			if (!CommandIsReadOnly(pstmt))
 			{
@@ -1757,7 +1757,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
 
 	foreach(list_item, raw_parsetree_list)
 	{
-		RawStmt    *parsetree = (RawStmt *) lfirst(list_item);
+		RawStmt    *parsetree = castNode(RawStmt, lfirst(list_item));
 		List	   *stmt_list;
 		CachedPlanSource *plansource;
 
@@ -1859,7 +1859,7 @@ _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
 
 	foreach(list_item, raw_parsetree_list)
 	{
-		RawStmt    *parsetree = (RawStmt *) lfirst(list_item);
+		RawStmt    *parsetree = castNode(RawStmt, lfirst(list_item));
 		CachedPlanSource *plansource;
 
 		plansource = CreateOneShotCachedPlan(parsetree,
@@ -2018,7 +2018,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 
 		foreach(lc2, stmt_list)
 		{
-			PlannedStmt *stmt = (PlannedStmt *) lfirst(lc2);
+			PlannedStmt *stmt = castNode(PlannedStmt, lfirst(lc2));
 			bool		canSetTag = stmt->canSetTag;
 			DestReceiver *dest;
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a8e35fecccdcc06d717bb8bbeb2b15b35bd40f55..a4edea08a3e30fbc2378adcce21147a41cc77d3e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -788,7 +788,7 @@ stmtmulti:	stmtmulti ';' stmt
 					if ($1 != NIL)
 					{
 						/* update length of previous stmt */
-						updateRawStmtEnd((RawStmt *) llast($1), @2);
+						updateRawStmtEnd(castNode(RawStmt, llast($1)), @2);
 					}
 					if ($3 != NULL)
 						$$ = lappend($1, makeRawStmt($3, @2 + 1));
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index c43ef19df5c51eb173fb3bddd0dd742ca7f622bc..4b732724177e59778f022eb29757cd2b92b728f0 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -1502,8 +1502,7 @@ transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
 			sublink = (SubLink *) transformExprRecurse(pstate,
 													   (Node *) sublink);
 
-			qtree = (Query *) sublink->subselect;
-			Assert(IsA(qtree, Query));
+			qtree = castNode(Query, sublink->subselect);
 
 			/* Check subquery returns required number of columns */
 			if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns)
@@ -1578,8 +1577,7 @@ transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
 
 		sublink = (SubLink *) tle->expr;
 		Assert(sublink->subLinkType == MULTIEXPR_SUBLINK);
-		qtree = (Query *) sublink->subselect;
-		Assert(IsA(qtree, Query));
+		qtree = castNode(Query, sublink->subselect);
 
 		/* Build a Param representing the current subquery output column */
 		tle = (TargetEntry *) list_nth(qtree->targetList, maref->colno - 1);
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 6660929dec748dc4b8698af985e93f776b827e86..8feec0b72b22228ca535c51bacae57e598d9528f 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -720,7 +720,7 @@ typeStringToTypeName(const char *str)
 	 */
 	if (list_length(raw_parsetree_list) != 1)
 		goto fail;
-	stmt = (SelectStmt *) ((RawStmt *) linitial(raw_parsetree_list))->stmt;
+	stmt = (SelectStmt *) castNode(RawStmt, linitial(raw_parsetree_list))->stmt;
 	if (stmt == NULL ||
 		!IsA(stmt, SelectStmt) ||
 		stmt->distinctClause != NIL ||
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 864d45ff1289699e73ba37533caade16d80b87a6..481868bf53d5dbfc95ab745aae1388f91450917a 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -173,7 +173,7 @@ InsertRule(char *rulname,
 	if (event_qual != NULL)
 	{
 		/* Find query containing OLD/NEW rtable entries */
-		Query	   *qry = (Query *) linitial(action);
+		Query	   *qry = castNode(Query, linitial(action));
 
 		qry = getInsertSelectQuery(qry, NULL);
 		recordDependencyOnExpr(&myself, event_qual, qry->rtable,
@@ -286,7 +286,7 @@ DefineQueryRewrite(char *rulename,
 	 */
 	foreach(l, action)
 	{
-		query = (Query *) lfirst(l);
+		query = castNode(Query, lfirst(l));
 		if (query->resultRelation == 0)
 			continue;
 		/* Don't be fooled by INSERT/SELECT */
@@ -328,7 +328,7 @@ DefineQueryRewrite(char *rulename,
 		/*
 		 * ... the one action must be a SELECT, ...
 		 */
-		query = (Query *) linitial(action);
+		query = castNode(Query, linitial(action));
 		if (!is_instead ||
 			query->commandType != CMD_SELECT)
 			ereport(ERROR,
@@ -482,7 +482,7 @@ DefineQueryRewrite(char *rulename,
 
 		foreach(l, action)
 		{
-			query = (Query *) lfirst(l);
+			query = castNode(Query, lfirst(l));
 
 			if (!query->returningList)
 				continue;
@@ -813,7 +813,7 @@ setRuleCheckAsUser_Query(Query *qry, Oid userid)
 	{
 		CommonTableExpr *cte = (CommonTableExpr *) lfirst(l);
 
-		setRuleCheckAsUser_Query((Query *) cte->ctequery, userid);
+		setRuleCheckAsUser_Query(castNode(Query, cte->ctequery), userid);
 	}
 
 	/* If there are sublinks, search for them and process their RTEs */
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 62d49c8625f0e1d7b2f966c636792e1b5616ef05..b07d6c6cb9b83fe0297615ed373f36be6c229ce4 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -962,7 +962,7 @@ exec_simple_query(const char *query_string)
 	 */
 	foreach(parsetree_item, parsetree_list)
 	{
-		RawStmt    *parsetree = (RawStmt *) lfirst(parsetree_item);
+		RawStmt    *parsetree = castNode(RawStmt, lfirst(parsetree_item));
 		bool		snapshot_set = false;
 		const char *commandTag;
 		char		completionTag[COMPLETION_TAG_BUFSIZE];
@@ -1286,7 +1286,7 @@ exec_parse_message(const char *query_string,	/* string to execute */
 		bool		snapshot_set = false;
 		int			i;
 
-		raw_parse_tree = (RawStmt *) linitial(parsetree_list);
+		raw_parse_tree = castNode(RawStmt, linitial(parsetree_list));
 
 		/*
 		 * Get the command name for possible use in status display.
@@ -2148,7 +2148,7 @@ errdetail_execute(List *raw_parsetree_list)
 
 	foreach(parsetree_item, raw_parsetree_list)
 	{
-		RawStmt    *parsetree = (RawStmt *) lfirst(parsetree_item);
+		RawStmt    *parsetree = castNode(RawStmt, lfirst(parsetree_item));
 
 		if (IsA(parsetree->stmt, ExecuteStmt))
 		{
@@ -2502,9 +2502,8 @@ IsTransactionExitStmtList(List *pstmts)
 {
 	if (list_length(pstmts) == 1)
 	{
-		PlannedStmt *pstmt = (PlannedStmt *) linitial(pstmts);
+		PlannedStmt *pstmt = castNode(PlannedStmt, linitial(pstmts));
 
-		Assert(IsA(pstmt, PlannedStmt));
 		if (pstmt->commandType == CMD_UTILITY &&
 			IsTransactionExitStmt(pstmt->utilityStmt))
 			return true;
@@ -2518,9 +2517,8 @@ IsTransactionStmtList(List *pstmts)
 {
 	if (list_length(pstmts) == 1)
 	{
-		PlannedStmt *pstmt = (PlannedStmt *) linitial(pstmts);
+		PlannedStmt *pstmt = castNode(PlannedStmt, linitial(pstmts));
 
-		Assert(IsA(pstmt, PlannedStmt));
 		if (pstmt->commandType == CMD_UTILITY &&
 			IsA(pstmt->utilityStmt, TransactionStmt))
 			return true;
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 704be399cf7c0b435ddbd4362c65155e056797e5..e64ea2ed7678f4f914ad51844ca513c380684cd3 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -487,7 +487,7 @@ PortalStart(Portal portal, ParamListInfo params,
 				 * Create QueryDesc in portal's context; for the moment, set
 				 * the destination to DestNone.
 				 */
-				queryDesc = CreateQueryDesc((PlannedStmt *) linitial(portal->stmts),
+				queryDesc = CreateQueryDesc(castNode(PlannedStmt, linitial(portal->stmts)),
 											portal->sourceText,
 											GetActiveSnapshot(),
 											InvalidSnapshot,
@@ -1020,7 +1020,7 @@ FillPortalStore(Portal portal, bool isTopLevel)
 			break;
 
 		case PORTAL_UTIL_SELECT:
-			PortalRunUtility(portal, (PlannedStmt *) linitial(portal->stmts),
+			PortalRunUtility(portal, castNode(PlannedStmt, linitial(portal->stmts)),
 							 isTopLevel, true, treceiver, completionTag);
 			break;
 
@@ -1215,7 +1215,7 @@ PortalRunMulti(Portal portal,
 	 */
 	foreach(stmtlist_item, portal->stmts)
 	{
-		PlannedStmt *pstmt = (PlannedStmt *) lfirst(stmtlist_item);
+		PlannedStmt *pstmt = castNode(PlannedStmt, lfirst(stmtlist_item));
 
 		/*
 		 * If we got a cancel signal in prior command, quit
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 03062471774a50f9b88f6e95b448b140d02b8127..801a9634dc157086b626d5bb85e5fa1000fc5532 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1829,22 +1829,19 @@ UtilityContainsQuery(Node *parsetree)
 	switch (nodeTag(parsetree))
 	{
 		case T_DeclareCursorStmt:
-			qry = (Query *) ((DeclareCursorStmt *) parsetree)->query;
-			Assert(IsA(qry, Query));
+			qry = castNode(Query, ((DeclareCursorStmt *) parsetree)->query);
 			if (qry->commandType == CMD_UTILITY)
 				return UtilityContainsQuery(qry->utilityStmt);
 			return qry;
 
 		case T_ExplainStmt:
-			qry = (Query *) ((ExplainStmt *) parsetree)->query;
-			Assert(IsA(qry, Query));
+			qry = castNode(Query, ((ExplainStmt *) parsetree)->query);
 			if (qry->commandType == CMD_UTILITY)
 				return UtilityContainsQuery(qry->utilityStmt);
 			return qry;
 
 		case T_CreateTableAsStmt:
-			qry = (Query *) ((CreateTableAsStmt *) parsetree)->query;
-			Assert(IsA(qry, Query));
+			qry = castNode(Query, ((CreateTableAsStmt *) parsetree)->query);
 			if (qry->commandType == CMD_UTILITY)
 				return UtilityContainsQuery(qry->utilityStmt);
 			return qry;
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index c31c603fbf5ad111e7bbd166fb1b64ac24ba6b53..dffc92762bc0e1fd9e98436f56506302ef3d50da 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -975,7 +975,7 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
 	is_transient = false;
 	foreach(lc, plist)
 	{
-		PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc);
+		PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
 
 		if (plannedstmt->commandType == CMD_UTILITY)
 			continue;			/* Ignore utility statements */
@@ -1070,7 +1070,7 @@ cached_plan_cost(CachedPlan *plan, bool include_planner)
 
 	foreach(lc, plan->stmt_list)
 	{
-		PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc);
+		PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
 
 		if (plannedstmt->commandType == CMD_UTILITY)
 			continue;			/* Ignore utility statements */
@@ -1457,9 +1457,7 @@ QueryListGetPrimaryStmt(List *stmts)
 
 	foreach(lc, stmts)
 	{
-		Query	   *stmt = (Query *) lfirst(lc);
-
-		Assert(IsA(stmt, Query));
+		Query	   *stmt = castNode(Query, lfirst(lc));
 
 		if (stmt->canSetTag)
 			return stmt;
@@ -1478,12 +1476,10 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
 
 	foreach(lc1, stmt_list)
 	{
-		PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc1);
+		PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc1));
 		int			rt_index;
 		ListCell   *lc2;
 
-		Assert(IsA(plannedstmt, PlannedStmt));
-
 		if (plannedstmt->commandType == CMD_UTILITY)
 		{
 			/*
@@ -1549,9 +1545,7 @@ AcquirePlannerLocks(List *stmt_list, bool acquire)
 
 	foreach(lc, stmt_list)
 	{
-		Query	   *query = (Query *) lfirst(lc);
-
-		Assert(IsA(query, Query));
+		Query	   *query = castNode(Query, lfirst(lc));
 
 		if (query->commandType == CMD_UTILITY)
 		{
@@ -1618,9 +1612,9 @@ ScanQueryForLocks(Query *parsetree, bool acquire)
 	/* Recurse into subquery-in-WITH */
 	foreach(lc, parsetree->cteList)
 	{
-		CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
+		CommonTableExpr *cte = castNode(CommonTableExpr, lfirst(lc));
 
-		ScanQueryForLocks((Query *) cte->ctequery, acquire);
+		ScanQueryForLocks(castNode(Query, cte->ctequery), acquire);
 	}
 
 	/*
@@ -1648,7 +1642,7 @@ ScanQueryWalker(Node *node, bool *acquire)
 		SubLink    *sub = (SubLink *) node;
 
 		/* Do what we came for */
-		ScanQueryForLocks((Query *) sub->subselect, *acquire);
+		ScanQueryForLocks(castNode(Query, sub->subselect), *acquire);
 		/* Fall through to process lefthand args of SubLink */
 	}
 
@@ -1676,8 +1670,7 @@ PlanCacheComputeResultDesc(List *stmt_list)
 	{
 		case PORTAL_ONE_SELECT:
 		case PORTAL_ONE_MOD_WITH:
-			query = (Query *) linitial(stmt_list);
-			Assert(IsA(query, Query));
+			query = castNode(Query, linitial(stmt_list));
 			return ExecCleanTypeFromTL(query->targetList, false);
 
 		case PORTAL_ONE_RETURNING:
@@ -1686,8 +1679,7 @@ PlanCacheComputeResultDesc(List *stmt_list)
 			return ExecCleanTypeFromTL(query->returningList, false);
 
 		case PORTAL_UTIL_SELECT:
-			query = (Query *) linitial(stmt_list);
-			Assert(IsA(query, Query));
+			query = castNode(Query, linitial(stmt_list));
 			Assert(query->utilityStmt);
 			return UtilityTupleDescriptor(query->utilityStmt);
 
@@ -1744,7 +1736,7 @@ PlanCacheRelCallback(Datum arg, Oid relid)
 
 			foreach(lc, plansource->gplan->stmt_list)
 			{
-				PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc);
+				PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
 
 				if (plannedstmt->commandType == CMD_UTILITY)
 					continue;	/* Ignore utility statements */
@@ -1817,7 +1809,7 @@ PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue)
 		{
 			foreach(lc, plansource->gplan->stmt_list)
 			{
-				PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc);
+				PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
 				ListCell   *lc3;
 
 				if (plannedstmt->commandType == CMD_UTILITY)
@@ -1890,9 +1882,8 @@ ResetPlanCache(void)
 		 */
 		foreach(lc, plansource->query_list)
 		{
-			Query	   *query = (Query *) lfirst(lc);
+			Query	   *query = castNode(Query, lfirst(lc));
 
-			Assert(IsA(query, Query));
 			if (query->commandType != CMD_UTILITY ||
 				UtilityContainsQuery(query->utilityStmt))
 			{
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index e8ebc4684caf32ff167d765c07c3c7de462cf46c..3a3259bae27bb4cc0ff3191bd9f30d6189102513 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -153,9 +153,7 @@ PortalGetPrimaryStmt(Portal portal)
 
 	foreach(lc, portal->stmts)
 	{
-		PlannedStmt *stmt = (PlannedStmt *) lfirst(lc);
-
-		Assert(IsA(stmt, PlannedStmt));
+		PlannedStmt *stmt = castNode(PlannedStmt, lfirst(lc));
 
 		if (stmt->canSetTag)
 			return stmt;
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index b48146a362b1cbbd2b4422eae85bbb1728aae254..6fc3db07fe64d7ca46245e28fa759856d7a954ee 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3634,9 +3634,8 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
 
 			foreach(l2, plansource->query_list)
 			{
-				Query	   *q = (Query *) lfirst(l2);
+				Query	   *q = castNode(Query, lfirst(l2));
 
-				Assert(IsA(q, Query));
 				if (q->canSetTag)
 				{
 					if (q->commandType == CMD_INSERT ||
@@ -6825,8 +6824,7 @@ exec_simple_recheck_plan(PLpgSQL_expr *expr, CachedPlan *cplan)
 	 */
 	if (list_length(cplan->stmt_list) != 1)
 		return;
-	stmt = (PlannedStmt *) linitial(cplan->stmt_list);
-	Assert(IsA(stmt, PlannedStmt));
+	stmt = castNode(PlannedStmt, linitial(cplan->stmt_list));
 
 	/*
 	 * 2. It must be a RESULT plan --> no scan's required