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