* RelationGetIndexPredicate -- get the index predicate for an index * * We cache the result of transforming pg_index.indpred into an implicit-AND * node tree (suitable for use in planning). * If the rel is not an index or has no predicate, we return NIL. * Otherwise, the returned tree is copied into the caller's memory context. * (We don't want to return a pointer to the relcache copy, since
| 5287 | * disappear due to relcache invalidation.) |
| 5288 | */ |
| 5289 | List * |
| 5290 | RelationGetIndexPredicate(Relation relation) |
| 5291 | { |
| 5292 | List *result; |
| 5293 | Datum predDatum; |
| 5294 | bool isnull; |
| 5295 | char *predString; |
| 5296 | MemoryContext oldcxt; |
| 5297 | |
| 5298 | /* Quick exit if we already computed the result. */ |
| 5299 | if (relation->rd_indpred) |
| 5300 | return copyObject(relation->rd_indpred); |
| 5301 | |
| 5302 | /* Quick exit if there is nothing to do. */ |
| 5303 | if (relation->rd_indextuple == NULL || |
| 5304 | heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL)) |
| 5305 | return NIL; |
| 5306 | |
| 5307 | /* |
| 5308 | * We build the tree we intend to return in the caller's context. After |
| 5309 | * successfully completing the work, we copy it into the relcache entry. |
| 5310 | * This avoids problems if we get some sort of error partway through. |
| 5311 | */ |
| 5312 | predDatum = heap_getattr(relation->rd_indextuple, |
| 5313 | Anum_pg_index_indpred, |
| 5314 | GetPgIndexDescriptor(), |
| 5315 | &isnull); |
| 5316 | Assert(!isnull); |
| 5317 | predString = TextDatumGetCString(predDatum); |
| 5318 | result = (List *) stringToNode(predString); |
| 5319 | pfree(predString); |
| 5320 | |
| 5321 | /* |
| 5322 | * Run the expression through const-simplification and canonicalization. |
| 5323 | * This is not just an optimization, but is necessary, because the planner |
| 5324 | * will be comparing it to similarly-processed qual clauses, and may fail |
| 5325 | * to detect valid matches without this. This must match the processing |
| 5326 | * done to qual clauses in preprocess_expression()! (We can skip the |
| 5327 | * stuff involving subqueries, however, since we don't allow any in index |
| 5328 | * predicates.) |
| 5329 | */ |
| 5330 | result = (List *) eval_const_expressions(NULL, (Node *) result); |
| 5331 | |
| 5332 | result = (List *) canonicalize_qual((Expr *) result, false); |
| 5333 | |
| 5334 | /* Also convert to implicit-AND format */ |
| 5335 | result = make_ands_implicit((Expr *) result); |
| 5336 | |
| 5337 | /* May as well fix opfuncids too */ |
| 5338 | fix_opfuncids((Node *) result); |
| 5339 | |
| 5340 | /* Now save a copy of the completed tree in the relcache entry. */ |
| 5341 | oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt); |
| 5342 | relation->rd_indpred = copyObject(result); |
| 5343 | MemoryContextSwitchTo(oldcxt); |
| 5344 | |
| 5345 | return result; |
| 5346 | } |
no test coverage detected