Age Owner Branch data TLA 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 *
1424 noah@leadboat.com 39 :CBC 267 : create_queryEnv(void)
40 : : {
2571 kgrittn@postgresql.o 41 : 267 : return (QueryEnvironment *) palloc0(sizeof(QueryEnvironment));
42 : : }
43 : :
44 : : EphemeralNamedRelationMetadata
45 : 122609 : get_visible_ENR_metadata(QueryEnvironment *queryEnv, const char *refname)
46 : : {
47 : : EphemeralNamedRelation enr;
48 : :
49 [ - + ]: 122609 : Assert(refname != NULL);
50 : :
51 [ + + ]: 122609 : if (queryEnv == NULL)
52 : 122131 : return NULL;
53 : :
54 : 478 : enr = get_ENR(queryEnv, refname);
55 : :
56 [ + + ]: 478 : if (enr)
57 : 455 : return &(enr->md);
58 : :
59 : 23 : 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 : 342 : register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
70 : : {
71 [ - + ]: 342 : Assert(enr != NULL);
72 [ - + ]: 342 : Assert(get_ENR(queryEnv, enr->md.name) == NULL);
73 : :
74 : 342 : queryEnv->namedRelList = lappend(queryEnv->namedRelList, enr);
75 : 342 : }
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
2571 kgrittn@postgresql.o 82 :UBC 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
2571 kgrittn@postgresql.o 96 :CBC 1225 : get_ENR(QueryEnvironment *queryEnv, const char *name)
97 : : {
98 : : ListCell *lc;
99 : :
100 [ - + ]: 1225 : Assert(name != NULL);
101 : :
102 [ - + ]: 1225 : if (queryEnv == NULL)
2571 kgrittn@postgresql.o 103 :UBC 0 : return NULL;
104 : :
2571 kgrittn@postgresql.o 105 [ + + + + :CBC 1571 : foreach(lc, queryEnv->namedRelList)
+ + ]
106 : : {
107 : 1131 : EphemeralNamedRelation enr = (EphemeralNamedRelation) lfirst(lc);
108 : :
109 [ + + ]: 1131 : if (strcmp(enr->md.name, name) == 0)
110 : 785 : return enr;
111 : : }
112 : :
113 : 440 : 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 : 556 : ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd)
126 : : {
127 : : TupleDesc tupdesc;
128 : :
129 : : /* One, and only one, of these fields must be filled. */
130 [ - + ]: 556 : Assert((enrmd->reliddesc == InvalidOid) != (enrmd->tupdesc == NULL));
131 : :
132 [ - + ]: 556 : if (enrmd->tupdesc != NULL)
2571 kgrittn@postgresql.o 133 :UBC 0 : tupdesc = enrmd->tupdesc;
134 : : else
135 : : {
136 : : Relation relation;
137 : :
1910 andres@anarazel.de 138 :CBC 556 : relation = table_open(enrmd->reliddesc, NoLock);
2571 kgrittn@postgresql.o 139 : 556 : tupdesc = relation->rd_att;
1910 andres@anarazel.de 140 : 556 : table_close(relation, NoLock);
141 : : }
142 : :
2571 kgrittn@postgresql.o 143 : 556 : return tupdesc;
144 : : }
|