v0.patch.txt

application/octet-stream

Filename: v0.patch.txt
Type: application/octet-stream
Part: 0
Message: Re: support create index on virtual generated column.
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 2268cc27..bb3f2e63 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -1200,7 +1200,8 @@ heapam_index_build_range_scan(Relation heapRelation,
 	econtext->ecxt_scantuple = slot;
 
 	/* Set up execution state for predicate, if any. */
-	predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
+	predicate = ExecPrepareQual((List *)expand_generated_columns((Node *)indexInfo->ii_Predicate, heapRelation, InvalidOid),
+								estate);
 
 	/*
 	 * Prepare for scan of the base relation.  In a normal index build, we use
@@ -1758,7 +1759,8 @@ heapam_index_validate_scan(Relation heapRelation,
 	econtext->ecxt_scantuple = slot;
 
 	/* Set up execution state for predicate, if any. */
-	predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
+	predicate = ExecPrepareQual((List *)expand_generated_columns((Node *)indexInfo->ii_Predicate, heapRelation, InvalidOid),
+								estate);
 
 	/*
 	 * Prepare for scan of the base relation.  We need just those tuples
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9407c357..8c0fbfd8 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -81,6 +81,7 @@
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
 #include "utils/tuplesort.h"
+#include "rewrite/rewriteHandler.h"
 
 /* Potentially set by pg_upgrade_support functions */
 Oid			binary_upgrade_next_index_pg_class_oid = InvalidOid;
@@ -3029,6 +3030,7 @@ index_build(Relation heapRelation,
 	Oid			save_userid;
 	int			save_sec_context;
 	int			save_nestlevel;
+	List	   *save_ii_Predicate = NIL;
 
 	/*
 	 * sanity checks
@@ -3093,6 +3095,9 @@ index_build(Relation heapRelation,
 		pgstat_progress_update_multi_param(6, progress_index, progress_vals);
 	}
 
+	save_ii_Predicate = indexInfo->ii_Predicate;
+	indexInfo->ii_Predicate = (List *)expand_generated_columns((Node *)indexInfo->ii_Predicate,
+																heapRelation, InvalidOid);
 	/*
 	 * Call the access method's build procedure
 	 */
@@ -3100,6 +3105,8 @@ index_build(Relation heapRelation,
 											 indexInfo);
 	Assert(stats);
 
+	indexInfo->ii_Predicate = save_ii_Predicate;
+
 	/*
 	 * If this is an unlogged index, we may need to write out an init fork for
 	 * it -- but we must first check whether one already exists.  If, for
@@ -3246,7 +3253,8 @@ IndexCheckExclusion(Relation heapRelation,
 	econtext->ecxt_scantuple = slot;
 
 	/* Set up execution state for predicate, if any. */
-	predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
+	predicate = ExecPrepareQual((List *)expand_generated_columns((Node *)indexInfo->ii_Predicate, heapRelation, InvalidOid),
+								estate);
 
 	/*
 	 * Scan all live tuples in the base relation.
@@ -4309,3 +4317,38 @@ RestoreReindexState(const void *reindexstate)
 	/* Note the worker has its own transaction nesting level */
 	reindexingNestLevel = GetCurrentTransactionNestLevel();
 }
+
+
+Node *
+expand_generated_columns(Node *node, Relation relation, Oid relid)
+{
+	/*expand_VGC_context 	context;
+	TupleDesc			tupdesc;*/
+	bool 				opened_relation = false;
+
+	if (node == NULL || (relation == NULL && relid == InvalidOid))
+		return node;
+
+	if (relation == NULL)
+	{
+		relation = table_open(relid, NoLock);
+		opened_relation = true;
+	}
+
+	node = expand_generated_columns_in_expr(node, relation, 1);
+
+	/*tupdesc = RelationGetDescr(relation);
+
+	if ((tupdesc->constr && tupdesc->constr->has_generated_virtual))
+	{
+		context.relation = relation;
+		context.tupdesc = tupdesc;
+
+		node = expand_VGC_impl(node, &context);
+	}*/
+
+	if (opened_relation)
+		table_close(relation, NoLock);
+
+	return node;
+}
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index f66e80b7..69ba3c37 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -926,7 +926,8 @@ compute_index_stats(Relation onerel, double totalrows,
 		econtext->ecxt_scantuple = slot;
 
 		/* Set up execution state for predicate. */
-		predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
+		predicate = ExecPrepareQual((List *)expand_generated_columns((Node *)indexInfo->ii_Predicate, onerel, InvalidOid),
+									estate);
 
 		/* Compute and save index expression values */
 		exprvals = (Datum *) palloc(numrows * attr_cnt * sizeof(Datum));
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 9ab74c8d..f7cb7c70 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1123,6 +1123,7 @@ DefineIndex(ParseState *pstate,
 					 errmsg("index creation on system columns is not supported")));
 
 
+		/*
 		if (attno > 0 &&
 			TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
 			ereport(ERROR,
@@ -1132,6 +1133,7 @@ DefineIndex(ParseState *pstate,
 					stmt->isconstraint ?
 					errmsg("unique constraints on virtual generated columns are not supported") :
 					errmsg("indexes on virtual generated columns are not supported"));
+		*/
 	}
 
 	/*
@@ -1140,16 +1142,23 @@ DefineIndex(ParseState *pstate,
 	 */
 	if (indexInfo->ii_Expressions || indexInfo->ii_Predicate)
 	{
-		Bitmapset  *indexattrs = NULL;
+		Bitmapset  *indexattrsExpr = NULL;
+		Bitmapset  *indexattrsPred = NULL;
 		int			j;
 
-		pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
-		pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
+		pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrsExpr);
+		pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrsPred);
 
 		for (int i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
 		{
 			if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
-							  indexattrs))
+							  indexattrsExpr))
+				ereport(ERROR,
+						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 errmsg("index creation on system columns is not supported")));
+
+			if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
+							  indexattrsPred))
 				ereport(ERROR,
 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 						 errmsg("index creation on system columns is not supported")));
@@ -1161,7 +1170,7 @@ DefineIndex(ParseState *pstate,
 		 * RelationGetIndexExpressions() and RelationGetIndexPredicate().
 		 */
 		j = -1;
-		while ((j = bms_next_member(indexattrs, j)) >= 0)
+		while ((j = bms_next_member(indexattrsExpr, j)) >= 0)
 		{
 			AttrNumber	attno = j + FirstLowInvalidHeapAttributeNumber;
 
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 0634af96..5ebbb3ef 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -2416,8 +2416,8 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
 		attr = TupleDescAttr(slot_tupdesc, attnum - 1);
 
 		/* Internal error: somebody forgot to expand it. */
-		if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
-			elog(ERROR, "unexpected virtual generated column reference");
+		/*if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
+			elog(ERROR, "unexpected virtual generated column reference"); */
 
 		if (attr->attisdropped)
 			ereport(ERROR,
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index eb383812..3a865b19 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -388,7 +388,8 @@ ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
 			predicate = indexInfo->ii_PredicateState;
 			if (predicate == NULL)
 			{
-				predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
+				predicate = ExecPrepareQual((List *)expand_generated_columns((Node *)indexInfo->ii_Predicate, heapRelation, InvalidOid),
+											estate);
 				indexInfo->ii_PredicateState = predicate;
 			}
 
@@ -624,7 +625,8 @@ ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
 			predicate = indexInfo->ii_PredicateState;
 			if (predicate == NULL)
 			{
-				predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
+				predicate = ExecPrepareQual((List *)expand_generated_columns((Node *)indexInfo->ii_Predicate, heapRelation, InvalidOid),
+											estate);
 				indexInfo->ii_PredicateState = predicate;
 			}
 
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 3f5d4fa3..007e892f 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -35,6 +35,7 @@
 #include "optimizer/restrictinfo.h"
 #include "utils/lsyscache.h"
 #include "utils/selfuncs.h"
+#include "catalog/index.h"
 
 
 /* XXX see PartCollMatchesExprColl */
@@ -1094,6 +1095,7 @@ build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel,
 	List	   *result = NIL;
 	List	   *all_clauses = NIL;	/* not computed till needed */
 	ListCell   *lc;
+	Oid  		heapRelId = InvalidOid;
 
 	foreach(lc, rel->indexlist)
 	{
@@ -1127,14 +1129,18 @@ build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel,
 			}
 			else
 			{
+				heapRelId = (root->simple_rte_array[index->rel->relid])->relid;
+
 				/* Form all_clauses if not done already */
 				if (all_clauses == NIL)
 					all_clauses = list_concat_copy(clauses, other_clauses);
 
-				if (!predicate_implied_by(index->indpred, all_clauses, false))
+				if (!predicate_implied_by((List *)expand_generated_columns((Node *)index->indpred, NULL, heapRelId),
+										  all_clauses, false))
 					continue;	/* can't use it at all */
 
-				if (!predicate_implied_by(index->indpred, other_clauses, false))
+				if (!predicate_implied_by((List *)expand_generated_columns((Node *)index->indpred, NULL, heapRelId),
+										  other_clauses, false))
 					useful_predicate = true;
 			}
 		}
@@ -3944,6 +3950,7 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
 	bool		is_target_rel;
 	Relids		otherrels;
 	ListCell   *lc;
+	Oid  		heapRelId = InvalidOid;
 
 	/* Indexes are available only on base or "other" member relations. */
 	Assert(IS_SIMPLE_REL(rel));
@@ -4041,9 +4048,10 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
 		if (index->indpred == NIL)
 			continue;			/* ignore non-partial indexes here */
 
+		heapRelId = (root->simple_rte_array[index->rel->relid])->relid;
 		if (!index->predOK)		/* don't repeat work if already proven OK */
-			index->predOK = predicate_implied_by(index->indpred, clauselist,
-												 false);
+			index->predOK = predicate_implied_by((List *)expand_generated_columns((Node *)index->indpred, NULL, heapRelId),
+												 clauselist, false);
 
 		/* If rel is an update target, leave indrestrictinfo as set above */
 		if (is_target_rel)
@@ -4068,7 +4076,8 @@ check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
 			/* predicate_implied_by() assumes first arg is immutable */
 			if (contain_mutable_functions((Node *) rinfo->clause) ||
 				!predicate_implied_by(list_make1(rinfo->clause),
-									  index->indpred, false))
+									  (List *)expand_generated_columns((Node *)index->indpred, NULL, heapRelId),
+									  false))
 				index->indrestrictinfo = lappend(index->indrestrictinfo, rinfo);
 		}
 	}
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 9aee8226..015ec674 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -16,6 +16,9 @@
 
 #include "catalog/objectaddress.h"
 #include "nodes/execnodes.h"
+/*#include "rewrite/rewriteManip.h"
+
+#include "nodes/nodeFuncs.h"*/
 
 
 /*
@@ -59,6 +62,12 @@ typedef struct ValidateIndexState
 				tups_inserted;
 } ValidateIndexState;
 
+typedef struct expand_VGC_context
+{
+	Relation	relation;	/* the relation of the virtual generated column */
+	TupleDesc	tupdesc;
+} expand_VGC_context;
+
 extern void index_check_primary_key(Relation heapRel,
 									const IndexInfo *indexInfo,
 									bool is_alter_table,
@@ -223,4 +232,35 @@ itemptr_decode(ItemPointer itemptr, int64 encoded)
 	ItemPointerSet(itemptr, block, offset);
 }
 
+/*
+static Node *
+expand_VGC_impl(Node *node, expand_VGC_context *context)
+{
+	if (node == NULL)
+	{
+		
+	}
+	else if (IsA(node, Var))
+	{
+		int varattno = ((Var *)node)->varattno;
+
+		Form_pg_attribute attr = TupleDescAttr(context->tupdesc, varattno - 1);
+		if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
+		{
+			node = build_generation_expression(context->relation,
+											   varattno);
+			ChangeVarNodes(node, 1, 1, 0);
+		}
+		else
+			node = copyObject(node);
+	}
+	else
+		node = expression_tree_mutator(node, expand_VGC_impl, context);
+
+	return node;
+}
+*/
+
+extern Node *expand_generated_columns(Node *node, Relation relation, Oid relid);
+
 #endif							/* INDEX_H */