1 /*-------------------------------------------------------------------------
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.
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.
14 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
19 * src/backend/utils/misc/queryenvironment.c
21 *-------------------------------------------------------------------------
25 #include "access/table.h"
26 #include "utils/queryenvironment.h"
27 #include "utils/rel.h"
30 * Private state of a query environment.
32 struct QueryEnvironment
41 return (QueryEnvironment
*) palloc0(sizeof(QueryEnvironment
));
44 EphemeralNamedRelationMetadata
45 get_visible_ENR_metadata(QueryEnvironment
*queryEnv
, const char *refname
)
47 EphemeralNamedRelation enr
;
49 Assert(refname
!= NULL
);
54 enr
= get_ENR(queryEnv
, refname
);
63 * Register a named relation for use in the given environment.
65 * If this is intended exclusively for planning purposes, the tstate field can
69 register_ENR(QueryEnvironment
*queryEnv
, EphemeralNamedRelation enr
)
72 Assert(get_ENR(queryEnv
, enr
->md
.name
) == NULL
);
74 queryEnv
->namedRelList
= lappend(queryEnv
->namedRelList
, enr
);
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".
82 unregister_ENR(QueryEnvironment
*queryEnv
, const char *name
)
84 EphemeralNamedRelation match
;
86 match
= get_ENR(queryEnv
, name
);
88 queryEnv
->namedRelList
= list_delete(queryEnv
->namedRelList
, match
);
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.
95 EphemeralNamedRelation
96 get_ENR(QueryEnvironment
*queryEnv
, const char *name
)
100 Assert(name
!= NULL
);
102 if (queryEnv
== NULL
)
105 foreach(lc
, queryEnv
->namedRelList
)
107 EphemeralNamedRelation enr
= (EphemeralNamedRelation
) lfirst(lc
);
109 if (strcmp(enr
->md
.name
, name
) == 0)
117 * Gets the TupleDesc for a Ephemeral Named Relation, based on which field was
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.
125 ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd
)
129 /* One, and only one, of these fields must be filled. */
130 Assert((enrmd
->reliddesc
== InvalidOid
) != (enrmd
->tupdesc
== NULL
));
132 if (enrmd
->tupdesc
!= NULL
)
133 tupdesc
= enrmd
->tupdesc
;
138 relation
= table_open(enrmd
->reliddesc
, NoLock
);
139 tupdesc
= relation
->rd_att
;
140 table_close(relation
, NoLock
);