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-2017, PostgreSQL Global Development Group
15 : * Portions Copyright (c) 1994, Regents of the University of California
16 : *
17 : *
18 : * IDENTIFICATION
19 : * src/backend/backend/utils/misc/queryenvironment.c
20 : *
21 : *-------------------------------------------------------------------------
22 : */
23 : #include "postgres.h"
24 :
25 : #include "access/heapam.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 52 : create_queryEnv()
40 : {
41 52 : return (QueryEnvironment *) palloc0(sizeof(QueryEnvironment));
42 : }
43 :
44 : EphemeralNamedRelationMetadata
45 12811 : get_visible_ENR_metadata(QueryEnvironment *queryEnv, const char *refname)
46 : {
47 : EphemeralNamedRelation enr;
48 :
49 12811 : Assert(refname != NULL);
50 :
51 12811 : if (queryEnv == NULL)
52 12714 : return NULL;
53 :
54 97 : enr = get_ENR(queryEnv, refname);
55 :
56 97 : if (enr)
57 90 : return &(enr->md);
58 :
59 7 : 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 62 : register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
70 : {
71 62 : Assert(enr != NULL);
72 62 : Assert(get_ENR(queryEnv, enr->md.name) == NULL);
73 :
74 62 : queryEnv->namedRelList = lappend(queryEnv->namedRelList, enr);
75 62 : }
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 228 : get_ENR(QueryEnvironment *queryEnv, const char *name)
97 : {
98 : ListCell *lc;
99 :
100 228 : Assert(name != NULL);
101 :
102 228 : if (queryEnv == NULL)
103 0 : return NULL;
104 :
105 283 : foreach(lc, queryEnv->namedRelList)
106 : {
107 204 : EphemeralNamedRelation enr = (EphemeralNamedRelation) lfirst(lc);
108 :
109 204 : if (strcmp(enr->md.name, name) == 0)
110 149 : return enr;
111 : }
112 :
113 79 : 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 104 : ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd)
126 : {
127 : TupleDesc tupdesc;
128 :
129 : /* One, and only one, of these fields must be filled. */
130 104 : Assert((enrmd->reliddesc == InvalidOid) != (enrmd->tupdesc == NULL));
131 :
132 104 : if (enrmd->tupdesc != NULL)
133 0 : tupdesc = enrmd->tupdesc;
134 : else
135 : {
136 : Relation relation;
137 :
138 104 : relation = heap_open(enrmd->reliddesc, NoLock);
139 104 : tupdesc = relation->rd_att;
140 104 : heap_close(relation, NoLock);
141 : }
142 :
143 104 : return tupdesc;
144 : }
|