Skip to content

Commit 7f4c523

Browse files
committed
Draft
1 parent d555d5a commit 7f4c523

1 file changed

Lines changed: 116 additions & 64 deletions

File tree

src/backend/parser/cypher_clause.c

Lines changed: 116 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -636,9 +636,7 @@ static Query *transform_cypher_union(cypher_parsestate *cpstate, cypher_clause *
636636

637637
/*
638638
* transform_cypher_union_tree
639-
* Recursively transform leaves and internal nodes of a set-op tree,
640-
* derived from postgresql's transformSetOperationTree. A lot of
641-
* the general logic is similar, with adjustments made for AGE.
639+
* Recursively transform leaves and internal nodes of a set-op tree.
642640
*
643641
* In addition to returning the transformed node, if targetlist isn't NULL
644642
* then we return a list of its non-resjunk TargetEntry nodes. For a leaf
@@ -688,7 +686,7 @@ transform_cypher_union_tree(cypher_parsestate *cpstate, cypher_clause *clause, b
688686

689687
if (isLeaf) {
690688
//process leaf return
691-
Query *returnQuery;
689+
Query *query;
692690
char returnName[32];
693691
RangeTblEntry *rte PG_USED_FOR_ASSERTS_ONLY;
694692
RangeTblRef *rtr;
@@ -715,25 +713,25 @@ transform_cypher_union_tree(cypher_parsestate *cpstate, cypher_clause *clause, b
715713
* is hiding it.
716714
*/
717715

718-
returnQuery = cypher_parse_sub_analyze_union((cypher_clause *) clause, cpstate, NULL, false, false);
716+
query = cypher_parse_sub_analyze_union((cypher_clause *) clause, cpstate, NULL, false, false);
719717
/*
720718
* Check for bogus references to Vars on the current query level (but
721719
* upper-level references are okay). Normally this can't happen
722720
* because the namespace will be empty, but it could happen if we are
723721
* inside a rule.
724722
*/
725-
if (pstate->p_namespace && contain_vars_of_level((Node *) returnQuery, 1))
723+
if (pstate->p_namespace && contain_vars_of_level((Node *) query, 1))
726724
ereport(ERROR,
727725
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
728726
errmsg("UNION member statement cannot refer to other relations of same query level"),
729-
parser_errposition(pstate, locate_var_of_level((Node *) returnQuery, 1))));
727+
parser_errposition(pstate, locate_var_of_level((Node *) query, 1))));
730728

731729
/*
732730
* Extract a list of the non-junk TLEs for upper-level processing.
733731
*/
734732
if (targetlist) {
735733
*targetlist = NIL;
736-
foreach(tl, returnQuery->targetList) {
734+
foreach(tl, query->targetList) {
737735
TargetEntry *tle = (TargetEntry *) lfirst(tl);
738736

739737
if (!tle->resjunk)
@@ -745,7 +743,7 @@ transform_cypher_union_tree(cypher_parsestate *cpstate, cypher_clause *clause, b
745743
* Make the leaf query be a subquery in the top-level rangetable.
746744
*/
747745
snprintf(returnName, sizeof(returnName), "*SELECT* %d ", list_length(pstate->p_rtable) + 1);
748-
pnsi = addRangeTableEntryForSubquery(pstate, returnQuery, makeAlias(returnName, NIL), false, false);
746+
pnsi = addRangeTableEntryForSubquery(pstate, query, makeAlias(returnName, NIL), false, false);
749747
rte = pnsi->p_rte;
750748
rtr = makeNode(RangeTblRef);
751749
// assume new rte is at end
@@ -1058,9 +1056,6 @@ static Query *transform_cypher_match_union_label(cypher_parsestate *cpstate, cyp
10581056

10591057
assign_query_collations(pstate, qry);
10601058

1061-
// this must be done after collations, for reliable comparison of exprs
1062-
if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1063-
parse_check_aggregates(pstate, qry);
10641059

10651060
return qry;
10661061

@@ -1078,15 +1073,16 @@ Query *cypher_parse_sub_analyze_union_label(cypher_parsestate *cpstate, char *sc
10781073
RangeVar *label_range_var = makeRangeVar(schema_name, rel_name, -1);
10791074
Node *alias = makeAlias(var_name, NIL);
10801075

1081-
ParseNamespaceItem *pnsi = addRangeTableEntry(pstate, label_range_var, alias, label_range_var->inh, true);
1076+
ParseNamespaceItem *pnsi = addRangeTableEntry(pstate, label_range_var, alias, false, true);
10821077
addNSItemToQuery(pstate, pnsi, true, true, true);
10831078

1079+
10841080
// make target entry and add it
10851081
query->targetList =
10861082
lappend(query->targetList,
10871083
makeTargetEntry(
1088-
(Expr *)make_vertex_expr(cpstate, pnsi),
1089-
++pstate->p_next_resno,
1084+
(Expr *)make_vertex_expr(state, pnsi),
1085+
pstate->p_next_resno++,
10901086
var_name,
10911087
false));
10921088

@@ -1095,7 +1091,7 @@ Query *cypher_parse_sub_analyze_union_label(cypher_parsestate *cpstate, char *sc
10951091
lappend(query->targetList,
10961092
makeTargetEntry(
10971093
scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_ID, -1),
1098-
++pstate->p_next_resno,
1094+
pstate->p_next_resno++,
10991095
make_id_alias(var_name),
11001096
false));
11011097

@@ -1104,7 +1100,7 @@ Query *cypher_parse_sub_analyze_union_label(cypher_parsestate *cpstate, char *sc
11041100
lappend(query->targetList,
11051101
makeTargetEntry(
11061102
scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_PROPERTIES, -1),
1107-
++pstate->p_next_resno,
1103+
pstate->p_next_resno++,
11081104
make_property_alias(var_name),
11091105
false));
11101106

@@ -1131,22 +1127,18 @@ transform_cypher_union_tree_label(cypher_parsestate *cpstate, bool isTopLevel, L
11311127

11321128
// Guard against queue overflow due to overly complex set-expressions
11331129
check_stack_depth();
1134-
if (label_tree_node->larg) {
1135-
//process leaf return
1136-
Query *returnQuery;
1137-
char returnName[32];
1130+
if (!label_tree_node->larg) {
11381131
RangeTblEntry *rte PG_USED_FOR_ASSERTS_ONLY;
11391132
RangeTblRef *rtr;
11401133
ListCell *tl;
1141-
returnQuery = cypher_parse_sub_analyze_union_label(cpstate, cpstate->graph_name, label_tree_node->label_name, label_tree_node->label_name);
1142-
1134+
Query *query = cypher_parse_sub_analyze_union_label(cpstate, cpstate->graph_name, label_tree_node->label_name, label_tree_node->label_name);
11431135

11441136
/*
11451137
* Extract a list of the non-junk TLEs for upper-level processing.
11461138
*/
11471139
if (targetlist) {
11481140
*targetlist = NIL;
1149-
foreach(tl, returnQuery->targetList) {
1141+
foreach(tl, query->targetList) {
11501142
TargetEntry *tle = (TargetEntry *) lfirst(tl);
11511143

11521144
if (!tle->resjunk)
@@ -1157,8 +1149,8 @@ transform_cypher_union_tree_label(cypher_parsestate *cpstate, bool isTopLevel, L
11571149
/*
11581150
* Make the leaf query be a subquery in the top-level rangetable.
11591151
*/
1160-
snprintf(returnName, sizeof(returnName), "*SELECT* %d ", list_length(pstate->p_rtable) + 1);
1161-
pnsi = addRangeTableEntryForSubquery(pstate, returnQuery, makeAlias(returnName, NIL), false, false);
1152+
//snprintf(returnName, sizeof(returnName), "*SELECT* %d ", list_length(pstate->p_rtable) + 1);
1153+
pnsi = addRangeTableEntryForSubquery(pstate, query, makeAlias(label_tree_node->label_name, NIL), false, false);
11621154
rte = pnsi->p_rte;
11631155
rtr = makeNode(RangeTblRef);
11641156
// assume new rte is at end
@@ -4205,6 +4197,28 @@ static char *make_endid_alias(char *var_name) {
42054197
return str;
42064198
}
42074199

4200+
static cypher_label_tree_node *push_new_label(cypher_label_tree_node * root, char *label_name) {
4201+
if (!root) {
4202+
root = make_ag_node(cypher_label_tree_node);
4203+
root->label_name = label_name;
4204+
root->larg = NULL;
4205+
root->rarg = NULL;
4206+
return root;
4207+
}
4208+
4209+
4210+
if (root->larg == NULL) {
4211+
cypher_label_tree_node *larg = make_ag_node(cypher_label_tree_node);
4212+
larg->label_name = label_name;
4213+
root->larg = larg;
4214+
root->rarg = push_new_label(root->rarg , label_name);
4215+
} else {
4216+
root->rarg = push_new_label(root->rarg , label_name);
4217+
}
4218+
4219+
return root;
4220+
}
4221+
42084222
//ltree
42094223
#include "ltree.h"
42104224

@@ -4247,10 +4261,6 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node
42474261
TargetEntry *te;
42484262
Node *expr;
42494263

4250-
/*
4251-
* If we are in a WHERE clause transform, we don't want to create new
4252-
* variables, we want to use the existing ones. So, error if otherwise.
4253-
*/
42544264
if (pstate->p_expr_kind == EXPR_KIND_WHERE) {
42554265
transform_entity *entity = find_transform_entity(cpstate, node->name, ENT_VERTEX);
42564266
if (entity)
@@ -4288,65 +4298,107 @@ static Expr *transform_cypher_node(cypher_parsestate *cpstate, cypher_node *node
42884298

42894299
int ltq_query_args[2];
42904300
ltq_query_args[0] = LookupTypeNameOid(pstate, makeTypeNameFromNameList(list_make2(makeString("public"), makeString("ltree"))), false);
4291-
ltq_query_args[1] = LookupTypeNameOid(pstate, makeTypeNameFromNameList(list_make2(makeString("public"), makeString("ltree"))), false);
4301+
ltq_query_args[1] = ltq_query_args[0];//LookupTypeNameOid(pstate, makeTypeNameFromNameList(list_make2(makeString("public"), makeString("ltree"))), false);
42924302

42934303
Oid ltree_contains_oid = LookupFuncName(list_make2(makeString("public"), makeString("ltree_risparent")), 2, &ltq_query_args, false);
42944304

42954305
ScanKeyData scan_keys[1];
4296-
ScanKeyInit(&scan_keys[0], Anum_ag_label_label_path, BTEqualStrategyNumber, ltree_contains_oid, label_lquery);
4306+
ScanKeyInit(&scan_keys[0], Anum_ag_label_label_path, 11, ltree_contains_oid, label_lquery);
42974307

42984308
Relation label_catalog = table_open(ag_label_relation_id(), AccessShareLock);
4309+
int count = 0;
42994310
SysScanDesc scan_desc = systable_beginscan(label_catalog, ag_label_label_index_id(), true, NULL, 1, scan_keys);
43004311

4301-
HeapTuple tuple = systable_getnext(scan_desc);
4312+
cypher_label_tree_node *root = NULL;
4313+
while(true) {
4314+
bool is_null;
4315+
HeapTuple tuple = systable_getnext(scan_desc);
4316+
4317+
if (!HeapTupleIsValid(tuple))
4318+
break;
43024319

4303-
if (!HeapTupleIsValid(tuple))
4304-
ereport(ERROR,
4305-
(errcode(ERRCODE_UNDEFINED_SCHEMA),
4306-
errmsg("not found %s", node->label)));
4307-
4308-
bool is_null;
4309-
rel_name = heap_getattr(tuple, Anum_ag_label_name, RelationGetDescr(label_catalog), &is_null);
4320+
Oid rel_graph_oid = heap_getattr(tuple, Anum_ag_label_graph, RelationGetDescr(label_catalog), &is_null);
4321+
4322+
if (rel_graph_oid != get_graph_oid(cpstate->graph_name))
4323+
continue;
4324+
4325+
rel_name = heap_getattr(tuple, Anum_ag_label_name, RelationGetDescr(label_catalog), &is_null);
4326+
4327+
root = push_new_label(root, rel_name);
4328+
count++;
4329+
}
43104330

43114331

43124332
systable_endscan(scan_desc);
43134333
table_close(label_catalog, AccessShareLock);
43144334

4315-
//rel_name = get_label_relation_name(node->label, cpstate->graph_oid);
4316-
label_range_var = makeRangeVar(schema_name, rel_name, -1);
4317-
alias = makeAlias(node->name, NIL);
4335+
if (count == 0)
4336+
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4337+
errmsg("no data found for %s", node->name),
4338+
parser_errposition(pstate, node->location)));
43184339

4319-
pnsi = addRangeTableEntry(pstate, label_range_var, alias, label_range_var->inh, true);
4320-
Assert(pnsi != NULL);
4340+
if (count == 1) {
4341+
//rel_name = get_label_relation_name(node->label, cpstate->graph_oid);
4342+
label_range_var = makeRangeVar(schema_name, rel_name, -1);
4343+
alias = makeAlias(node->name, NIL);
43214344

4322-
addNSItemToQuery(pstate, pnsi, true, true, true);
4345+
pnsi = addRangeTableEntry(pstate, label_range_var, alias, false, true);
4346+
Assert(pnsi != NULL);
43234347

4324-
resno = pstate->p_next_resno++;
4348+
addNSItemToQuery(pstate, pnsi, true, true, true);
43254349

4326-
expr = (Expr *)make_vertex_expr(cpstate, pnsi);
4350+
resno = pstate->p_next_resno++;
43274351

4328-
// make target entry and add it
4329-
te = makeTargetEntry(expr, resno, node->name, false);
4330-
*target_list = lappend(*target_list, te);
4352+
expr = (Expr *)make_vertex_expr(cpstate, pnsi);
43314353

4332-
// id field
4333-
Node *id = scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_ID, -1);
4334-
resno = pstate->p_next_resno++;
4354+
// make target entry and add it
4355+
te = makeTargetEntry(expr, resno, node->name, false);
4356+
*target_list = lappend(*target_list, te);
43354357

4336-
te = makeTargetEntry(id, resno, make_id_alias(node->name), false);
4337-
*target_list = lappend(*target_list, te);
4358+
// id field
4359+
Node *id = scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_ID, -1);
4360+
resno = pstate->p_next_resno++;
43384361

4339-
/*
4340-
* properties field
4341-
*/
4342-
Node *props = scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_PROPERTIES, -1);
4343-
resno = pstate->p_next_resno++;
4362+
te = makeTargetEntry(id, resno, make_id_alias(node->name), false);
4363+
*target_list = lappend(*target_list, te);
43444364

4345-
te = makeTargetEntry(props, resno, make_property_alias(node->name), false);
4346-
*target_list = lappend(*target_list, te);
4365+
// properties field
4366+
Node *props = scanNSItemForColumn(pstate, pnsi, 0, AG_VERTEX_COLNAME_PROPERTIES, -1);
4367+
resno = pstate->p_next_resno++;
43474368

4369+
te = makeTargetEntry(props, resno, make_property_alias(node->name), false);
4370+
*target_list = lappend(*target_list, te);
43484371

4349-
return expr;
4372+
4373+
return expr;
4374+
4375+
} else {
4376+
4377+
4378+
Query *query = transform_cypher_match_union_label(cpstate, root);
4379+
ParseNamespaceItem *pnsi = addRangeTableEntryForSubquery(pstate, query, makeAlias(node->name, NIL), false, true);
4380+
4381+
if (list_length(pstate->p_rtable) > 1) {
4382+
List *namespace = NULL;
4383+
int rtindex = 0;
4384+
4385+
rtindex = list_length(pstate->p_rtable);
4386+
4387+
if (pnsi->p_rte != rt_fetch(rtindex, pstate->p_rtable))
4388+
ereport(ERROR,
4389+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4390+
errmsg("rte must be last entry in p_rtable")));
4391+
4392+
namespace = list_make1(pnsi);
4393+
4394+
checkNameSpaceConflicts(pstate, pstate->p_namespace, namespace);
4395+
}
4396+
4397+
addNSItemToQuery(pstate, pnsi, true, false, true);
4398+
4399+
return scanNSItemForColumn(pstate, pnsi, 0, node->name, -1);
4400+
4401+
}
43504402
}
43514403

43524404
static Node *make_edge_expr(cypher_parsestate *cpstate, ParseNamespaceItem *pnsi) {

0 commit comments

Comments
 (0)