Skip to content

Commit a97def9

Browse files
committed
Fix Return *
The interal columns that PostGraph uses won't be displayed anymore on RETURN *
1 parent f1ce7db commit a97def9

File tree

4 files changed

+186
-6
lines changed

4 files changed

+186
-6
lines changed

regress/expected/new_cypher.out

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,62 @@
1+
-- Regression tests don't preload extensions, gotta load it first
12
LOAD 'postgraph';
3+
-- Basic Graph creation
24
CREATE GRAPH new_cypher;
35
NOTICE: graph "new_cypher" has been created
46
create_graph
57
--------------
68

79
(1 row)
810

11+
-- Assign Graph to use
912
USE GRAPH new_cypher;
10-
NOTICE: graph "new_cypher" is being used
13+
NOTICE: graph oid: 18547 is being used
1114
use_graph
1215
-----------
1316

1417
(1 row)
1518

19+
-- Reuse Name, should throw error
20+
CREATE GRAPH new_cypher;
21+
ERROR: graph "new_cypher" already exists
22+
-- Graph Does not exist, should throw error
23+
USE GRAPH new_cypher;
24+
ERROR: duplicate key value violates unique constraint "session_graph_use_index"
25+
DETAIL: Key (pid, graph_oid)=(11301, 18547) already exists.
26+
-- Old Grammar is at least partially plugged in.
1627
RETURN 1 as a;
17-
WARNING: snapshot 0x2786be8 still active
28+
WARNING: snapshot 0x168d938 still active
1829
a
1930
---
2031
1
2132
(1 row)
2233

34+
CREATE (n);
35+
WARNING: snapshot 0x168d938 still active
36+
_null | _id_n___ | _pr_n | n | _create_clause
37+
-------+----------+-------+---+----------------
38+
| 0 | {} | |
39+
(1 row)
40+
41+
CREATE (n) RETURN n;
42+
WARNING: snapshot 0x168d938 still active
43+
n
44+
--------------------------------------------------------
45+
{"id": 281474976710657, "label": "", "properties": {}}
46+
(1 row)
47+
48+
--CREATE (n) RETURN *;
49+
MATCH (n) RETURN n;
50+
WARNING: snapshot 0x168d938 still active
51+
n
52+
--------------------------------------------------------
53+
{"id": 281474976710657, "label": "", "properties": {}}
54+
(1 row)
55+
56+
MATCH (n) RETURN *;
57+
WARNING: snapshot 0x168d938 still active
58+
n
59+
--------------------------------------------------------
60+
{"id": 281474976710657, "label": "", "properties": {}}
61+
(1 row)
62+

src/backend/parser/cypher_analyze.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,37 @@ void parse_analyze_fini(void){
162162
parse_analyze_hook = NULL;
163163
}
164164

165+
166+
static FuncExpr *make_utility_func_expr(char *graph_name, char *function_name) {
167+
Const *c = makeConst(TEXTOID, -1, InvalidOid, strlen(graph_name), CStringGetTextDatum(graph_name), false, false);
168+
169+
Oid func_oid = get_ag_func_oid("create_graph", 1, TEXTOID);
170+
171+
return makeFuncExpr(func_oid, VOIDOID, list_make1(c), InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL);
172+
}
173+
174+
static Query *
175+
cypher_graph_utility(ParseState *pstate, const char *graph_name, char *function_name) {
176+
Query *query;
177+
TargetEntry *tle;
178+
FuncExpr *func_expr;
179+
180+
query = makeNode(Query);
181+
query->commandType = CMD_SELECT;
182+
query->targetList = NIL;
183+
184+
func_expr = make_utility_func_expr(graph_name, function_name);
185+
186+
// Create the target entry
187+
tle = makeTargetEntry((Expr *)func_expr, pstate->p_next_resno++, "create_graph", false);
188+
query->targetList = lappend(query->targetList, tle);
189+
190+
query->rtable = pstate->p_rtable;
191+
query->jointree = makeFromExpr(pstate->p_joinlist, NULL);
192+
return query;
193+
}
194+
195+
165196
/*
166197
* Creates the function expression that represents the clause. Adds the
167198
* extensible node that represents the metadata that the clause needs to

src/backend/parser/cypher_item.c

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,111 @@ TargetEntry *transform_cypher_item(cypher_parsestate *cpstate, Node *node,
5959
colname, resjunk);
6060
}
6161

62+
/*
63+
* expandNSItemAttrs -
64+
* Workhorse for "*" expansion: produce a list of targetentries
65+
* for the attributes of the nsitem
66+
*
67+
* pstate->p_next_resno determines the resnos assigned to the TLEs.
68+
* The referenced columns are marked as requiring SELECT access.
69+
*/
70+
List *
71+
expand_NS_Item_Attrs(ParseState *pstate, ParseNamespaceItem *nsitem,
72+
int sublevels_up, int location)
73+
{
74+
RangeTblEntry *rte = nsitem->p_rte;
75+
List *names,
76+
*vars;
77+
ListCell *name,
78+
*var;
79+
List *te_list = NIL;
80+
81+
vars = expandNSItemVars(nsitem, sublevels_up, location, &names);
82+
83+
/*
84+
* Require read access to the table. This is normally redundant with the
85+
* markVarForSelectPriv calls below, but not if the table has zero
86+
* columns. We need not do anything if the nsitem is for a join: its
87+
* component tables will have been marked ACL_SELECT when they were added
88+
* to the rangetable. (This step changes things only for the target
89+
* relation of UPDATE/DELETE, which cannot be under a join.)
90+
*/
91+
if (rte->rtekind == RTE_RELATION)
92+
rte->requiredPerms |= ACL_SELECT;
93+
94+
forboth(name, names, var, vars)
95+
{
96+
char *label = strVal(lfirst(name));
97+
Var *varnode = (Var *) lfirst(var);
98+
TargetEntry *te;
99+
if (strlen(label) < 2 || (strlen(label) >= 2 && label[0] == '_' && label[1] == '_')) {
100+
te = makeTargetEntry((Expr *) varnode,
101+
(AttrNumber) pstate->p_next_resno++,
102+
label,
103+
false);
104+
te_list = lappend(te_list, te);
105+
106+
/* Require read access to each column */
107+
markVarForSelectPriv(pstate, varnode);
108+
}
109+
}
110+
111+
Assert(name == NULL && var == NULL); /* lists not the same length? */
112+
113+
return te_list;
114+
}
115+
116+
/*
117+
* ExpandAllTables()
118+
* Transforms '*' (in the target list) into a list of targetlist entries.
119+
*
120+
* tlist entries are generated for each relation visible for unqualified
121+
* column name access. We do not consider qualified-name-only entries because
122+
* that would include input tables of aliasless JOINs, NEW/OLD pseudo-entries,
123+
* etc.
124+
*
125+
* The referenced relations/columns are marked as requiring SELECT access.
126+
*/
127+
static List *
128+
Expand_All_Tables(ParseState *pstate, int location)
129+
{
130+
List *target = NIL;
131+
bool found_table = false;
132+
ListCell *l;
133+
134+
foreach(l, pstate->p_namespace)
135+
{
136+
ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
137+
138+
/* Ignore table-only items */
139+
if (!nsitem->p_cols_visible)
140+
continue;
141+
/* Should not have any lateral-only items when parsing targetlist */
142+
Assert(!nsitem->p_lateral_only);
143+
/* Remember we found a p_cols_visible item */
144+
found_table = true;
145+
146+
target = list_concat(target,
147+
expand_NS_Item_Attrs(pstate,
148+
nsitem,
149+
0,
150+
location));
151+
}
152+
153+
/*
154+
* Check for "SELECT *;". We do it this way, rather than checking for
155+
* target == NIL, because we want to allow SELECT * FROM a zero_column
156+
* table.
157+
*/
158+
if (!found_table)
159+
ereport(ERROR,
160+
(errcode(ERRCODE_SYNTAX_ERROR),
161+
errmsg("SELECT * with no tables specified is not valid"),
162+
parser_errposition(pstate, location)));
163+
164+
return target;
165+
}
166+
62167
// see transformTargetList()
63168
List *transform_cypher_item_list(cypher_parsestate *cpstate, List *item_list,
64169
List **groupClause, ParseExprKind expr_kind)
@@ -77,8 +182,8 @@ List *transform_cypher_item_list(cypher_parsestate *cpstate, List *item_list,
77182
ResTarget *item = lfirst(li);
78183
TargetEntry *te;
79184

80-
cpstate->prop_node = NULL;
81-
cpstate->prop_name = NULL;
185+
cpstate->prop_node = NULL;
186+
cpstate->prop_name = NULL;
82187

83188
if (expand_star) {
84189
if (IsA(item->val, ColumnRef)) {
@@ -93,14 +198,16 @@ List *transform_cypher_item_list(cypher_parsestate *cpstate, List *item_list,
93198
errmsg("Invalid number of fields for *"),
94199
parser_errposition(pstate, cref->location)));
95200

96-
target_list = list_concat(target_list, ExpandAllTables(pstate, cref->location));
201+
target_list = list_concat(target_list, Expand_All_Tables(pstate, cref->location));
97202
continue;
98203
}
99204
}
100205
}
101206
/* clear the exprHasAgg flag to check transform for an aggregate */
102207
cpstate->exprHasAgg = false;
103208

209+
// if (item->name[0] == '_' && item->name[1] == '_')
210+
// continue;
104211
/* transform the item */
105212
te = transform_cypher_item(cpstate, item->val, NULL, expr_kind, item->name, false);
106213

src/include/parser/cypher_expr.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,7 @@
3232

3333
Node *transform_cypher_expr(cypher_parsestate *cpstate, Node *expr,
3434
ParseExprKind expr_kind);
35-
35+
List *
36+
expand_NS_Item_Attrs(ParseState *pstate, ParseNamespaceItem *nsitem,
37+
int sublevels_up, int location);
3638
#endif

0 commit comments

Comments
 (0)