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 */