Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * queryenvironment.c 4 : * Query environment, to store context-specific values like ephemeral named 5 : * relations. Initial use is for named tuplestores for delta information 6 : * from "normal" relations. 7 : * 8 : * The initial implementation uses a list because the number of such relations 9 : * in any one context is expected to be very small. If that becomes a 10 : * performance problem, the implementation can be changed with no other impact 11 : * on callers, since this is an opaque structure. This is the reason to 12 : * require a create function. 13 : * 14 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group 15 : * Portions Copyright (c) 1994, Regents of the University of California 16 : * 17 : * 18 : * IDENTIFICATION 19 : * src/backend/utils/misc/queryenvironment.c 20 : * 21 : *------------------------------------------------------------------------- 22 : */ 23 : #include "postgres.h" 24 : 25 : #include "access/table.h" 26 : #include "utils/queryenvironment.h" 27 : #include "utils/rel.h" 28 : 29 : /* 30 : * Private state of a query environment. 31 : */ 32 : struct QueryEnvironment 33 : { 34 : List *namedRelList; 35 : }; 36 : 37 : 38 : QueryEnvironment * 39 534 : create_queryEnv(void) 40 : { 41 534 : return (QueryEnvironment *) palloc0(sizeof(QueryEnvironment)); 42 : } 43 : 44 : EphemeralNamedRelationMetadata 45 258990 : get_visible_ENR_metadata(QueryEnvironment *queryEnv, const char *refname) 46 : { 47 : EphemeralNamedRelation enr; 48 : 49 : Assert(refname != NULL); 50 : 51 258990 : if (queryEnv == NULL) 52 258038 : return NULL; 53 : 54 952 : enr = get_ENR(queryEnv, refname); 55 : 56 952 : if (enr) 57 910 : return &(enr->md); 58 : 59 42 : return NULL; 60 : } 61 : 62 : /* 63 : * Register a named relation for use in the given environment. 64 : * 65 : * If this is intended exclusively for planning purposes, the tstate field can 66 : * be left NULL; 67 : */ 68 : void 69 684 : register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr) 70 : { 71 : Assert(enr != NULL); 72 : Assert(get_ENR(queryEnv, enr->md.name) == NULL); 73 : 74 684 : queryEnv->namedRelList = lappend(queryEnv->namedRelList, enr); 75 684 : } 76 : 77 : /* 78 : * Unregister an ephemeral relation by name. This will probably be a rarely 79 : * used function, but seems like it should be provided "just in case". 80 : */ 81 : void 82 0 : unregister_ENR(QueryEnvironment *queryEnv, const char *name) 83 : { 84 : EphemeralNamedRelation match; 85 : 86 0 : match = get_ENR(queryEnv, name); 87 0 : if (match) 88 0 : queryEnv->namedRelList = list_delete(queryEnv->namedRelList, match); 89 0 : } 90 : 91 : /* 92 : * This returns an ENR if there is a name match in the given collection. It 93 : * must quietly return NULL if no match is found. 94 : */ 95 : EphemeralNamedRelation 96 1762 : get_ENR(QueryEnvironment *queryEnv, const char *name) 97 : { 98 : ListCell *lc; 99 : 100 : Assert(name != NULL); 101 : 102 1762 : if (queryEnv == NULL) 103 0 : return NULL; 104 : 105 2304 : foreach(lc, queryEnv->namedRelList) 106 : { 107 2112 : EphemeralNamedRelation enr = (EphemeralNamedRelation) lfirst(lc); 108 : 109 2112 : if (strcmp(enr->md.name, name) == 0) 110 1570 : return enr; 111 : } 112 : 113 192 : return NULL; 114 : } 115 : 116 : /* 117 : * Gets the TupleDesc for a Ephemeral Named Relation, based on which field was 118 : * filled. 119 : * 120 : * When the TupleDesc is based on a relation from the catalogs, we count on 121 : * that relation being used at the same time, so that appropriate locks will 122 : * already be held. Locking here would be too late anyway. 123 : */ 124 : TupleDesc 125 1112 : ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd) 126 : { 127 : TupleDesc tupdesc; 128 : 129 : /* One, and only one, of these fields must be filled. */ 130 : Assert((enrmd->reliddesc == InvalidOid) != (enrmd->tupdesc == NULL)); 131 : 132 1112 : if (enrmd->tupdesc != NULL) 133 0 : tupdesc = enrmd->tupdesc; 134 : else 135 : { 136 : Relation relation; 137 : 138 1112 : relation = table_open(enrmd->reliddesc, NoLock); 139 1112 : tupdesc = relation->rd_att; 140 1112 : table_close(relation, NoLock); 141 : } 142 : 143 1112 : return tupdesc; 144 : }