From 76d1d41047c06116ddc560088458d15c966868dc Mon Sep 17 00:00:00 2001
From: Timur Magomedov <t.magomedov@postgrespro.ru>
Date: Wed, 17 Sep 2025 17:15:00 +0300
Subject: [PATCH 1/2] Assert corrrect node tags when casting to VciScanState

---
 contrib/vci/executor/vci_agg.c          |  6 ++++++
 contrib/vci/executor/vci_plan.c         |  3 +++
 contrib/vci/executor/vci_scan.c         | 12 ++++++++++++
 contrib/vci/executor/vci_sort.c         |  4 +++-
 contrib/vci/include/vci_aggref_impl.inc |  1 +
 5 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/contrib/vci/executor/vci_agg.c b/contrib/vci/executor/vci_agg.c
index 705610b58a3..be24bb0980e 100644
--- a/contrib/vci/executor/vci_agg.c
+++ b/contrib/vci/executor/vci_agg.c
@@ -527,6 +527,8 @@ lookup_hash_entry_vector(VciAggState *aggstate,
 	uint16	   *skip_list;
 	int			slot_index;
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 	skip_list = vci_CSGetSkipFromVirtualTuples(scanstate->vector_set);
 
 	/* Clear the tuple */
@@ -786,6 +788,8 @@ agg_fill_hash_table_vector(VciAggState *aggstate)
 	ExprContext *tmpcontext;
 	VciScanState *scanstate = (VciScanState *) outerPlanState(aggstate);
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 	/*
 	 * get state info from node
 	 */
@@ -1306,6 +1310,8 @@ vci_agg_BeginCustomPlan(CustomScanState *node, EState *estate, int eflags)
 		{
 			VciScanState *scanstate = (VciScanState *) outerPlanState(aggstate);
 
+			Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 			aggstate->hash_input_values = palloc(sizeof(Datum *) * aggstate->num_hash_needed);
 			aggstate->hash_input_isnull = palloc(sizeof(bool *) * aggstate->num_hash_needed);
 
diff --git a/contrib/vci/executor/vci_plan.c b/contrib/vci/executor/vci_plan.c
index c6146789c3a..dcc78802655 100644
--- a/contrib/vci/executor/vci_plan.c
+++ b/contrib/vci/executor/vci_plan.c
@@ -175,7 +175,10 @@ static VciScanState *
 search_scan_state(PlanState *node, Plan *target)
 {
 	if (node->plan == target)
+	{
+		Assert(node->type == T_CustomScanState);
 		return (VciScanState *) node;
+	}
 
 	if (outerPlanState(node))
 	{
diff --git a/contrib/vci/executor/vci_scan.c b/contrib/vci/executor/vci_scan.c
index fbf9ce5ffc5..158c6c58e22 100644
--- a/contrib/vci/executor/vci_scan.c
+++ b/contrib/vci/executor/vci_scan.c
@@ -97,6 +97,8 @@ vci_scan_BeginCustomPlan(CustomScanState *node, EState *estate, int eflags)
 	vci_initexpr_t initexpr = VCI_INIT_EXPR_NONE;
 	TupleDesc	scanDesc;
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 	if (ScanDirectionIsBackward(estate->es_direction))
 		elog(ERROR, "VCI Scan does not support backward scan");
 
@@ -237,6 +239,8 @@ vci_scan_ExecCustomPlan(CustomScanState *cstate)
 {
 	VciScanState *scanstate = (VciScanState *) cstate;
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 	return VciExecProcScanTuple(scanstate);
 }
 
@@ -457,6 +461,8 @@ vci_scan_EndCustomPlan(CustomScanState *node)
 	VciScanState *scanstate = (VciScanState *) node;
 	TableScanDesc scanDesc;
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 	scan = (VciScan *) scanstate->vci.css.ss.ps.plan;
 
 	scanDesc = scanstate->vci.css.ss.ss_currentScanDesc;
@@ -486,6 +492,7 @@ vci_scan_ReScanCustomPlan(CustomScanState *node)
 
 	scanstate = (VciScanState *) node;
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
 	/* Rescan EvalPlanQual tuple if we're inside an EvalPlanQual recheck */
 	Assert(scanstate->vci.css.ss.ps.state->es_epq_active == NULL);
 
@@ -497,6 +504,8 @@ vci_scan_MarkPosCustomPlan(CustomScanState *node)
 {
 	VciScanState *scanstate = (VciScanState *) node;
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 	vci_mark_pos_vector_set_from_column_store(scanstate);
 }
 
@@ -505,6 +514,8 @@ vci_scan_RestrPosCustomPlan(CustomScanState *node)
 {
 	VciScanState *scanstate = (VciScanState *) node;
 
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+
 	ExecClearTuple(scanstate->vci.css.ss.ss_ScanTupleSlot);
 
 	vci_restr_pos_vector_set_from_column_store(scanstate);
@@ -523,6 +534,7 @@ vci_scan_ExplainCustomPlanTargetRel(CustomScanState *node, ExplainState *es)
 	RangeTblEntry *rte;
 
 	scanstate = (VciScanState *) node;
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
 	scan = (VciScan *) scanstate->vci.css.ss.ps.plan;
 	scanrelid = scan->scanrelid;
 
diff --git a/contrib/vci/executor/vci_sort.c b/contrib/vci/executor/vci_sort.c
index 2e91762ad7a..029e02739ab 100644
--- a/contrib/vci/executor/vci_sort.c
+++ b/contrib/vci/executor/vci_sort.c
@@ -85,7 +85,9 @@ vci_sort_ExecCustomPlan(CustomScanState *node)
 
 		for (;;)
 		{
-			slot = VciExecProcScanTuple((VciScanState *) outerNode);
+			VciScanState *scanstate = (VciScanState *) outerNode;
+			Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
+			slot = VciExecProcScanTuple(scanstate);
 
 			if (TupIsNull(slot))
 				break;
diff --git a/contrib/vci/include/vci_aggref_impl.inc b/contrib/vci/include/vci_aggref_impl.inc
index 18a11b0bf66..95fba4d19ee 100644
--- a/contrib/vci/include/vci_aggref_impl.inc
+++ b/contrib/vci/include/vci_aggref_impl.inc
@@ -62,6 +62,7 @@ VCI_ADVANCE_AGGREF_FUNC(VciAggState *aggstate,
 #endif							/* SELECT VCI_TRANS_INPUTS_ARG */
 
 	scanstate = (VciScanState *) outerPlanState(aggstate);
+	Assert(scanstate->vci.css.ss.ps.type == T_CustomScanState);
 	skip_list = vci_CSGetSkipFromVirtualTuples(scanstate->vector_set);
 
 #if VCI_TRANS_INPUTS_ARG == VCI_TRANS_INPUTS_0
-- 
2.43.0

