v1.patch.txt

application/octet-stream

Filename: v1.patch.txt
Type: application/octet-stream
Part: 1
Message: Re: support create index on virtual generated column.
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 9ab74c8d..63540cfb 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -594,6 +594,7 @@ DefineIndex(ParseState *pstate,
 	Oid			root_save_userid;
 	int			root_save_sec_context;
 	int			root_save_nestlevel;
+	Node	   *whereClause = NULL;
 
 	root_save_nestlevel = NewGUCNestLevel();
 
@@ -905,8 +906,11 @@ DefineIndex(ParseState *pstate,
 	/*
 	 * Validate predicate, if given
 	 */
-	if (stmt->whereClause)
-		CheckPredicate((Expr *) stmt->whereClause);
+	if (stmt->whereClause){
+		/* Expand virtual generated columns in expressions */
+		whereClause = ExpandVirtualGeneratedColumns(copyObject(stmt->whereClause), rel, InvalidOid);
+		CheckPredicate((Expr *) whereClause);
+	}
 
 	/*
 	 * Parse AM-specific options, convert to text array form, validate.
@@ -925,7 +929,7 @@ DefineIndex(ParseState *pstate,
 							  numberOfKeyAttributes,
 							  accessMethodId,
 							  NIL,	/* expressions, NIL for now */
-							  make_ands_implicit((Expr *) stmt->whereClause),
+							  make_ands_implicit((Expr *) whereClause),
 							  stmt->unique,
 							  stmt->nulls_not_distinct,
 							  !concurrent,
@@ -948,6 +952,11 @@ DefineIndex(ParseState *pstate,
 					  root_save_userid, root_save_sec_context,
 					  &root_save_nestlevel);
 
+	/* Expand virtual generated columns in expressions */
+	if (indexInfo->ii_Expressions)
+		indexInfo->ii_Expressions =
+			(List *)ExpandVirtualGeneratedColumns((Node *)indexInfo->ii_Expressions, rel, InvalidOid);
+
 	/*
 	 * Extra checks when creating a PRIMARY KEY index.
 	 */
@@ -1122,8 +1131,8 @@ DefineIndex(ParseState *pstate,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("index creation on system columns is not supported")));
 
-
-		if (attno > 0 &&
+		/* allow virtual generated columns in include(...)*/
+		if (attno > 0 && i < numberOfKeyAttributes &&
 			TupleDescAttr(RelationGetDescr(rel), attno - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
 			ereport(ERROR,
 					errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1135,13 +1144,12 @@ DefineIndex(ParseState *pstate,
 	}
 
 	/*
-	 * Also check for system and generated columns used in expressions or
-	 * predicates.
+	 * Also check for system columns used in expressions or predicates.
 	 */
 	if (indexInfo->ii_Expressions || indexInfo->ii_Predicate)
 	{
 		Bitmapset  *indexattrs = NULL;
-		int			j;
+		/*int			j;*/
 
 		pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
 		pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
@@ -1160,7 +1168,7 @@ DefineIndex(ParseState *pstate,
 		 * could be supported, but it needs support in
 		 * RelationGetIndexExpressions() and RelationGetIndexPredicate().
 		 */
-		j = -1;
+		/*j = -1;
 		while ((j = bms_next_member(indexattrs, j)) >= 0)
 		{
 			AttrNumber	attno = j + FirstLowInvalidHeapAttributeNumber;
@@ -1172,7 +1180,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")));
-		}
+		}*/
 	}
 
 	/* Is index safe for others to ignore?  See set_indexsafe_procflags() */
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 0572ab42..7b531628 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -91,6 +91,7 @@
 #include "utils/resowner.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
+#include "rewrite/rewriteHandler.h"
 
 #define RELCACHE_INIT_FILEMAGIC		0x573266	/* version ID value */
 
@@ -5102,6 +5103,8 @@ RelationGetIndexExpressions(Relation relation)
 	bool		isnull;
 	char	   *exprsString;
 	MemoryContext oldcxt;
+	Datum		heapRelidDatum;
+	Oid         heapRelid;
 
 	/* Quick exit if we already computed the result. */
 	if (relation->rd_indexprs)
@@ -5138,6 +5141,15 @@ RelationGetIndexExpressions(Relation relation)
 	/* May as well fix opfuncids too */
 	fix_opfuncids((Node *) result);
 
+	heapRelidDatum = heap_getattr(relation->rd_indextuple,
+							 Anum_pg_index_indrelid,
+							 GetPgIndexDescriptor(),
+							 &isnull);
+	Assert(!isnull);
+	heapRelid = DatumGetObjectId(heapRelidDatum);
+
+	result = (List *)ExpandVirtualGeneratedColumns((Node *) result, NULL, heapRelid);
+
 	/* Now save a copy of the completed tree in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
 	relation->rd_indexprs = copyObject(result);
@@ -5215,6 +5227,8 @@ RelationGetIndexPredicate(Relation relation)
 	bool		isnull;
 	char	   *predString;
 	MemoryContext oldcxt;
+	Datum		heapRelidDatum;
+	Oid         heapRelid;
 
 	/* Quick exit if we already computed the result. */
 	if (relation->rd_indpred)
@@ -5258,6 +5272,15 @@ RelationGetIndexPredicate(Relation relation)
 	/* May as well fix opfuncids too */
 	fix_opfuncids((Node *) result);
 
+	heapRelidDatum = heap_getattr(relation->rd_indextuple,
+							 Anum_pg_index_indrelid,
+							 GetPgIndexDescriptor(),
+							 &isnull);
+	Assert(!isnull);
+	heapRelid = DatumGetObjectId(heapRelidDatum);
+
+	result = (List *)ExpandVirtualGeneratedColumns((Node *) result, NULL, heapRelid);
+
 	/* Now save a copy of the completed tree in the relcache entry. */
 	oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
 	relation->rd_indpred = copyObject(result);
@@ -7019,3 +7042,46 @@ ResOwnerReleaseRelation(Datum res)
 
 	RelationCloseCleanup((Relation) DatumGetPointer(res));
 }
+
+Node *
+ExpandVirtualGeneratedColumns(Node *node, Relation heapRelation, Oid heapRelId)
+{
+	bool 				 opened_relation = false;
+	TupleDesc			 tupdesc;
+
+	if (node == NULL || (heapRelation == NULL && heapRelId == InvalidOid))
+		return node;
+
+	if (heapRelation == NULL)
+	{
+		heapRelation = table_open(heapRelId, NoLock);
+		opened_relation = true;
+	}
+
+	tupdesc = RelationGetDescr(heapRelation);
+	if ((tupdesc->constr && tupdesc->constr->has_generated_virtual))
+	{
+		int				j;
+		Bitmapset		*indexattrs = NULL;
+
+		pull_varattnos(node, 1, &indexattrs);
+
+		j = -1;
+		while ((j = bms_next_member(indexattrs, j)) >= 0)
+		{
+			AttrNumber	attno = j + FirstLowInvalidHeapAttributeNumber;
+
+			if (attno > 0 &&
+				TupleDescAttr(tupdesc, attno - 1)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
+			{
+				node = expand_generated_columns_in_expr(node, heapRelation, 1);
+				break;
+			}
+		}
+	}
+
+	if (opened_relation)
+		table_close(heapRelation, NoLock);
+
+	return node;
+}
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 89c27aa1..07e70273 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -161,4 +161,6 @@ extern PGDLLIMPORT bool criticalRelcachesBuilt;
 /* should be used only by relcache.c and postinit.c */
 extern PGDLLIMPORT bool criticalSharedRelcachesBuilt;
 
+extern Node *ExpandVirtualGeneratedColumns(Node *node, Relation heapRelation, Oid heapRelId);
+
 #endif							/* RELCACHE_H */