Coverage Report

Created: 2026-08-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}