/src/postgres/src/backend/utils/misc/queryenvironment.c
Line | Count | Source |
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-2026, 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 | | create_queryEnv(void) |
40 | 0 | { |
41 | 0 | return palloc0_object(QueryEnvironment); |
42 | 0 | } |
43 | | |
44 | | EphemeralNamedRelationMetadata |
45 | | get_visible_ENR_metadata(QueryEnvironment *queryEnv, const char *refname) |
46 | 0 | { |
47 | 0 | EphemeralNamedRelation enr; |
48 | |
|
49 | 0 | Assert(refname != NULL); |
50 | |
|
51 | 0 | if (queryEnv == NULL) |
52 | 0 | return NULL; |
53 | | |
54 | 0 | enr = get_ENR(queryEnv, refname); |
55 | |
|
56 | 0 | if (enr) |
57 | 0 | return &(enr->md); |
58 | | |
59 | 0 | return NULL; |
60 | 0 | } |
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 | | register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr) |
70 | 0 | { |
71 | 0 | Assert(enr != NULL); |
72 | 0 | Assert(get_ENR(queryEnv, enr->md.name) == NULL); |
73 | |
|
74 | 0 | queryEnv->namedRelList = lappend(queryEnv->namedRelList, enr); |
75 | 0 | } |
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 | | unregister_ENR(QueryEnvironment *queryEnv, const char *name) |
83 | 0 | { |
84 | 0 | 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 | | get_ENR(QueryEnvironment *queryEnv, const char *name) |
97 | 0 | { |
98 | 0 | ListCell *lc; |
99 | |
|
100 | 0 | Assert(name != NULL); |
101 | |
|
102 | 0 | if (queryEnv == NULL) |
103 | 0 | return NULL; |
104 | | |
105 | 0 | foreach(lc, queryEnv->namedRelList) |
106 | 0 | { |
107 | 0 | EphemeralNamedRelation enr = (EphemeralNamedRelation) lfirst(lc); |
108 | |
|
109 | 0 | if (strcmp(enr->md.name, name) == 0) |
110 | 0 | return enr; |
111 | 0 | } |
112 | | |
113 | 0 | return NULL; |
114 | 0 | } |
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 | | ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd) |
126 | 0 | { |
127 | 0 | TupleDesc tupdesc; |
128 | | |
129 | | /* One, and only one, of these fields must be filled. */ |
130 | 0 | Assert((enrmd->reliddesc == InvalidOid) != (enrmd->tupdesc == NULL)); |
131 | |
|
132 | 0 | if (enrmd->tupdesc != NULL) |
133 | 0 | tupdesc = enrmd->tupdesc; |
134 | 0 | else |
135 | 0 | { |
136 | 0 | Relation relation; |
137 | |
|
138 | 0 | relation = table_open(enrmd->reliddesc, NoLock); |
139 | 0 | tupdesc = relation->rd_att; |
140 | 0 | table_close(relation, NoLock); |
141 | 0 | } |
142 | |
|
143 | 0 | return tupdesc; |
144 | 0 | } |