PostgreSQL Source Code git master
Loading...
Searching...
No Matches
parse_graphtable.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * parse_graphtable.c
4 * parsing of GRAPH_TABLE
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/parser/parse_graphtable.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include "access/genam.h"
19#include "access/htup_details.h"
20#include "access/table.h"
23#include "miscadmin.h"
24#include "nodes/makefuncs.h"
26#include "parser/parse_expr.h"
28#include "parser/parse_node.h"
29#include "utils/fmgroids.h"
30#include "utils/lsyscache.h"
31#include "utils/relcache.h"
32#include "utils/syscache.h"
33
34
35/*
36 * Return human-readable name of the type of graph element pattern in
37 * GRAPH_TABLE clause, usually for error message purpose.
38 */
39static const char *
41{
42 switch (gepkind)
43 {
44 case VERTEX_PATTERN:
45 return "vertex";
47 return "edge pointing left";
49 return "edge pointing right";
51 return "edge pointing any direction";
52 case PAREN_EXPR:
53 return "nested path pattern";
54 }
55
56 /*
57 * When a GraphElementPattern is constructed by the parser, it will set a
58 * value from the GraphElementPatternKind enum. But we may get here if the
59 * GraphElementPatternKind value stored in a catalog is corrupted.
60 */
61 return "unknown";
62}
63
64/*
65 * Transform a property reference.
66 *
67 * A property reference is parsed as a ColumnRef of the form:
68 * <variable>.<property>. If <variable> is one of the variables bound to an
69 * element pattern in the graph pattern and <property> can be resolved as a
70 * property of the property graph, then we return a GraphPropertyRef node
71 * representing the property reference. If the <variable> exists in the graph
72 * pattern but <property> does not exist in the property graph, we raise an
73 * error. However, if <variable> does not exist in the graph pattern, we return
74 * NULL to let the caller handle it as some other kind of ColumnRef. The
75 * variables bound to the element patterns in the graph pattern are expected to
76 * be collected in the GraphTableParseState.
77 */
78Node *
80{
82
83 if (!gpstate)
84 return NULL;
85
86 if (list_length(cref->fields) == 2)
87 {
88 Node *field1 = linitial(cref->fields);
89 Node *field2 = lsecond(cref->fields);
90 char *elvarname;
91 char *propname;
92
93 if (IsA(field1, A_Star) || IsA(field2, A_Star))
94 {
98 errmsg("\"*\" is not supported here"),
99 parser_errposition(pstate, cref->location));
100 else
103 errmsg("\"*\" not allowed here"),
104 parser_errposition(pstate, cref->location));
105 }
106
107 elvarname = strVal(field1);
109
110 if (list_member(gpstate->variables, field1))
111 {
115
120 errmsg("property \"%s\" does not exist", propname));
122
123 gpr->location = cref->location;
124 gpr->elvarname = elvarname;
125 gpr->propid = pgpform->oid;
126 gpr->typeId = pgpform->pgptypid;
127 gpr->typmod = pgpform->pgptypmod;
128 gpr->collation = pgpform->pgpcollation;
129
131
132 return (Node *) gpr;
133 }
134 }
135
136 return NULL;
137}
138
139/*
140 * Transform a label expression.
141 *
142 * A label expression is parsed as either a ColumnRef with a single field or a
143 * label expression like label disjunction. The single field in the ColumnRef is
144 * treated as a label name and transformed to a GraphLabelRef node. The label
145 * expression is recursively transformed into an expression tree containg
146 * GraphLabelRef nodes corresponding to the names of the labels appearing in the
147 * expression. If any label name cannot be resolved to a label in the property
148 * graph, an error is raised.
149 */
150static Node *
152{
153 Node *result;
154
155 if (labelexpr == NULL)
156 return NULL;
157
159
160 switch (nodeTag(labelexpr))
161 {
162 case T_ColumnRef:
163 {
164 ColumnRef *cref = (ColumnRef *) labelexpr;
165 const char *labelname;
166 Oid labelid;
168
169 Assert(list_length(cref->fields) == 1);
170 labelname = strVal(linitial(cref->fields));
171
173 if (!labelid)
176 errmsg("label \"%s\" does not exist in property graph \"%s\"", labelname, get_rel_name(gpstate->graphid)));
177
179 lref->labelid = labelid;
180 lref->location = cref->location;
181
182 result = (Node *) lref;
183 break;
184 }
185
186 case T_BoolExpr:
187 {
188 BoolExpr *be = (BoolExpr *) labelexpr;
189 ListCell *lc;
190 List *args = NIL;
191
192 foreach(lc, be->args)
193 {
194 Node *arg = (Node *) lfirst(lc);
195
197 args = lappend(args, arg);
198 }
199
200 result = (Node *) makeBoolExpr(be->boolop, args, be->location);
201 break;
202 }
203
204 default:
205 /* should not reach here */
206 elog(ERROR, "unsupported label expression node: %d", (int) nodeTag(labelexpr));
207 result = NULL; /* keep compiler quiet */
208 break;
209 }
210
211 return result;
212}
213
214/*
215 * Transform a GraphElementPattern.
216 *
217 * Transform the label expression and the where clause in the element pattern
218 * given by GraphElementPattern. The variable name in the GraphElementPattern is
219 * added to the list of variables in the GraphTableParseState which is used to
220 * resolve property references in this element pattern or elsewhere in the
221 * GRAPH_TABLE.
222 */
223static Node *
225{
227
228 if (gep->kind != VERTEX_PATTERN && !IS_EDGE_PATTERN(gep->kind))
231 errmsg("unsupported element pattern kind: \"%s\"", get_gep_kind_name(gep->kind)));
232
233 if (gep->quantifier)
236 errmsg("element pattern quantifier is not supported")));
237
238 if (gep->variable)
239 gpstate->variables = lappend(gpstate->variables, makeString(pstrdup(gep->variable)));
240
241 gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr);
242
243 gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE);
244 assign_expr_collations(pstate, gep->whereClause);
245
246 return (Node *) gep;
247}
248
249/*
250 * Transform a path term (list of GraphElementPattern's).
251 */
252static Node *
254{
255 List *result = NIL;
256
258 result = lappend(result,
260
261 return (Node *) result;
262}
263
264/*
265 * Transform a path pattern list (list of path terms).
266 */
267static Node *
269{
270 List *result = NIL;
271
272 /* Grammar doesn't allow empty path pattern list */
274
275 /*
276 * We do not support multiple path patterns in one GRAPH_TABLE clause
277 * right now. But we may do so in future.
278 */
279 if (list_length(path_pattern) != 1)
282 errmsg("multiple path patterns in one GRAPH_TABLE clause not supported")));
283
285 result = lappend(result, transformPathTerm(pstate, path_term));
286
287 return (Node *) result;
288}
289
290/*
291 * Transform a GraphPattern.
292 *
293 * A GraphPattern consists of a list of one or more path patterns and an
294 * optional where clause. Transform them. We use the previously constructure
295 * list of variables in the GraphTableParseState to resolve property references
296 * in the WHERE clause.
297 */
298Node *
300{
301 List *path_pattern_list = castNode(List,
302 transformPathPatternList(pstate, graph_pattern->path_pattern_list));
303
304 graph_pattern->path_pattern_list = path_pattern_list;
305 graph_pattern->whereClause = transformExpr(pstate, graph_pattern->whereClause, EXPR_KIND_WHERE);
306 assign_expr_collations(pstate, graph_pattern->whereClause);
307
308 return (Node *) graph_pattern;
309}
#define Assert(condition)
Definition c.h:942
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
List * lappend(List *list, void *datum)
Definition list.c:339
bool list_member(const List *list, const void *datum)
Definition list.c:661
char * get_rel_name(Oid relid)
Definition lsyscache.c:2148
Expr * makeBoolExpr(BoolExprType boolop, List *args, int location)
Definition makefuncs.c:420
char * pstrdup(const char *in)
Definition mcxt.c:1781
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define nodeTag(nodeptr)
Definition nodes.h:139
#define makeNode(_type_)
Definition nodes.h:161
#define castNode(_type_, nodeptr)
Definition nodes.h:182
static char * errmsg
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition parse_expr.c:121
static Node * transformPathTerm(ParseState *pstate, List *path_term)
static const char * get_gep_kind_name(GraphElementPatternKind gepkind)
static Node * transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep)
static Node * transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr)
Node * transformGraphPattern(ParseState *pstate, GraphPattern *graph_pattern)
static Node * transformPathPatternList(ParseState *pstate, List *path_pattern)
Node * transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref)
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
@ EXPR_KIND_WHERE
Definition parse_node.h:46
@ EXPR_KIND_SELECT_TARGET
Definition parse_node.h:54
GraphElementPatternKind
@ EDGE_PATTERN_RIGHT
@ VERTEX_PATTERN
@ EDGE_PATTERN_LEFT
@ PAREN_EXPR
@ EDGE_PATTERN_ANY
#define IS_EDGE_PATTERN(kind)
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define linitial(l)
Definition pg_list.h:178
#define lsecond(l)
Definition pg_list.h:183
#define foreach_node(type, var, lst)
Definition pg_list.h:496
END_CATALOG_STRUCT typedef FormData_pg_propgraph_property * Form_pg_propgraph_property
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
unsigned int Oid
static int fb(int x)
void check_stack_depth(void)
Definition stack_depth.c:95
Node * whereClause
List * path_pattern_list
Definition pg_list.h:54
Definition nodes.h:135
ParseExprKind p_expr_kind
Definition parse_node.h:228
GraphTableParseState * p_graph_table_pstate
Definition parse_node.h:238
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111
String * makeString(char *str)
Definition value.c:63
#define strVal(v)
Definition value.h:82