aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/misc/queryenvironment.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/misc/queryenvironment.c')
-rw-r--r--src/backend/utils/misc/queryenvironment.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/backend/utils/misc/queryenvironment.c b/src/backend/utils/misc/queryenvironment.c
new file mode 100644
index 00000000000..a0b10d402bd
--- /dev/null
+++ b/src/backend/utils/misc/queryenvironment.c
@@ -0,0 +1,144 @@
+/*-------------------------------------------------------------------------
+ *
+ * queryenvironment.c
+ * Query environment, to store context-specific values like ephemeral named
+ * relations. Initial use is for named tuplestores for delta information
+ * from "normal" relations.
+ *
+ * The initial implementation uses a list because the number of such relations
+ * in any one context is expected to be very small. If that becomes a
+ * performance problem, the implementation can be changed with no other impact
+ * on callers, since this is an opaque structure. This is the reason to
+ * require a create function.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/backend/utils/misc/queryenvironment.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "utils/queryenvironment.h"
+#include "utils/rel.h"
+
+/*
+ * Private state of a query environment.
+ */
+struct QueryEnvironment
+{
+ List *namedRelList;
+};
+
+
+QueryEnvironment *
+create_queryEnv()
+{
+ return (QueryEnvironment *) palloc0(sizeof(QueryEnvironment));
+}
+
+EphemeralNamedRelationMetadata
+get_visible_ENR_metadata(QueryEnvironment *queryEnv, const char *refname)
+{
+ EphemeralNamedRelation enr;
+
+ Assert(refname != NULL);
+
+ if (queryEnv == NULL)
+ return NULL;
+
+ enr = get_ENR(queryEnv, refname);
+
+ if (enr)
+ return &(enr->md);
+
+ return NULL;
+}
+
+/*
+ * Register a named relation for use in the given environment.
+ *
+ * If this is intended exclusively for planning purposes, the tstate field can
+ * be left NULL;
+ */
+void
+register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
+{
+ Assert(enr != NULL);
+ Assert(get_ENR(queryEnv, enr->md.name) == NULL);
+
+ queryEnv->namedRelList = lappend(queryEnv->namedRelList, enr);
+}
+
+/*
+ * Unregister an ephemeral relation by name. This will probably be a rarely
+ * used function, but seems like it should be provided "just in case".
+ */
+void
+unregister_ENR(QueryEnvironment *queryEnv, const char *name)
+{
+ EphemeralNamedRelation match;
+
+ match = get_ENR(queryEnv, name);
+ if (match)
+ queryEnv->namedRelList = list_delete(queryEnv->namedRelList, match);
+}
+
+/*
+ * This returns an ENR if there is a name match in the given collection. It
+ * must quietly return NULL if no match is found.
+ */
+EphemeralNamedRelation
+get_ENR(QueryEnvironment *queryEnv, const char *name)
+{
+ ListCell *lc;
+
+ Assert(name != NULL);
+
+ if (queryEnv == NULL)
+ return NULL;
+
+ foreach(lc, queryEnv->namedRelList)
+ {
+ EphemeralNamedRelation enr = (EphemeralNamedRelation) lfirst(lc);
+
+ if (strcmp(enr->md.name, name) == 0)
+ return enr;
+ }
+
+ return NULL;
+}
+
+/*
+ * Gets the TupleDesc for a Ephemeral Named Relation, based on which field was
+ * filled.
+ *
+ * When the TupleDesc is based on a relation from the catalogs, we count on
+ * that relation being used at the same time, so that appropriate locks will
+ * already be held. Locking here would be too late anyway.
+ */
+TupleDesc
+ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd)
+{
+ TupleDesc tupdesc;
+
+ /* One, and only one, of these fields must be filled. */
+ Assert((enrmd->reliddesc == InvalidOid) != (enrmd->tupdesc == NULL));
+
+ if (enrmd->tupdesc != NULL)
+ tupdesc = enrmd->tupdesc;
+ else
+ {
+ Relation relation;
+
+ relation = heap_open(enrmd->reliddesc, NoLock);
+ tupdesc = relation->rd_att;
+ heap_close(relation, NoLock);
+ }
+
+ return tupdesc;
+}