@@ -88,6 +88,7 @@ static char *make_endid_alias(char *var_name);
8888
8989static Node * make_vertex_expr (cypher_parsestate * cpstate , ParseNamespaceItem * pnsi );
9090static Node * make_edge_expr (cypher_parsestate * cpstate , ParseNamespaceItem * pnsi );
91+ static Node * make_vertex_expr_with_edge (cypher_parsestate * cpstate , ParseNamespaceItem * pnsi , ParseNamespaceItem * edge_pnsi );
9192
9293List *
9394transform_window_definitions (ParseState * pstate , List * windowdefs , List * * targetlist );
@@ -253,16 +254,39 @@ static Node *make_vertex_expr(cypher_parsestate *cpstate, ParseNamespaceItem *pn
253254}
254255
255256
257+ static Node * make_vertex_expr_with_edge (cypher_parsestate * cpstate , ParseNamespaceItem * pnsi , ParseNamespaceItem * edge_pnsi ) {
258+ ParseState * pstate = (ParseState * )cpstate ;
259+
260+ Oid func_oid = get_ag_func_oid ("build_vertex" , 3 , GRAPHIDOID , OIDOID , GTYPEOID );
261+
262+ Node * id = scanNSItemForColumn (pstate , edge_pnsi , 0 , "endid" , -1 );
263+
264+ Const * graph_oid_const = makeConst (OIDOID , -1 , InvalidOid , sizeof (Oid ),
265+ ObjectIdGetDatum (cpstate -> graph_oid ), false, true);
266+
267+ Node * props = scanNSItemForColumn (pstate , pnsi , 0 , AG_VERTEX_COLNAME_PROPERTIES , -1 );
268+
269+ List * args = list_make3 (id , graph_oid_const , props );
270+
271+ FuncExpr * func_expr = makeFuncExpr (func_oid , VERTEXOID , args , InvalidOid , InvalidOid , COERCE_EXPLICIT_CALL );
272+ func_expr -> location = -1 ;
273+
274+
275+ return (Node * )func_expr ;
276+ }
277+
278+
279+
256280static Node * make_edge_expr (cypher_parsestate * cpstate , ParseNamespaceItem * pnsi ) {
257281 ParseState * pstate = (ParseState * )cpstate ;
258282
259283 Oid func_oid = get_ag_func_oid ("build_edge" , 5 , GRAPHIDOID , GRAPHIDOID , GRAPHIDOID , OIDOID , GTYPEOID );
260284
261285 Node * id = scanNSItemForColumn (pstate , pnsi , 0 , AG_EDGE_COLNAME_ID , -1 );
262286
263- Node * start_id = scanNSItemForColumn (pstate , pnsi , 0 , AG_EDGE_COLNAME_START_ID , -1 );
287+ Node * start_id = scanNSItemForColumn (pstate , pnsi , 0 , "startid" , -1 );
264288
265- Node * end_id = scanNSItemForColumn (pstate , pnsi , 0 , AG_EDGE_COLNAME_END_ID , -1 );
289+ Node * end_id = scanNSItemForColumn (pstate , pnsi , 0 , "endid" , -1 );
266290
267291 Const * graph_oid_const = makeConst (OIDOID , -1 , InvalidOid , sizeof (Oid ),
268292 ObjectIdGetDatum (cpstate -> graph_oid ), false, true);
@@ -1067,34 +1091,6 @@ static Node *transform_srf_function(cypher_parsestate *cpstate, Node *n, RangeTb
10671091}
10681092
10691093
1070- static Node * transform_VLE_Function (cypher_parsestate * cpstate , Node * n , RangeTblEntry * * top_rte , int * top_rti , List * * namespace ) {
1071- ParseState * pstate = & cpstate -> pstate ;
1072-
1073- Assert (IsA (n , RangeFunction ));
1074-
1075- if (IsA (n , RangeFunction )) {
1076- RangeTblRef * rtr ;
1077- RangeTblEntry * rte ;
1078- ParseNamespaceItem * nsitem ;
1079- int rtindex ;
1080-
1081- nsitem = transformRangeFunction (cpstate , (RangeFunction * ) n );
1082- rte = nsitem -> p_rte ;
1083- rtindex = list_length (pstate -> p_rtable );
1084- Assert (rte == rt_fetch (rtindex , pstate -> p_rtable ));
1085- * top_rte = rte ;
1086- * top_rti = rtindex ;
1087- * namespace = list_make1 (nsitem );
1088- rtr = makeNode (RangeTblRef );
1089- rtr -> rtindex = rtindex ;
1090- return (Node * ) rtr ;
1091- }
1092-
1093- return NULL ;
1094- }
1095-
1096-
1097-
10981094
10991095// setNamespaceLateralState - subroutine to update LATERAL flags in a namespace list.
11001096static void setNamespaceLateralState (List * namespace , bool lateral_only , bool lateral_ok ) {
@@ -1163,9 +1159,9 @@ add_vertex_to_query(cypher_parsestate *cpstate, Query *query, cypher_node *node)
11631159{
11641160 ParseState * pstate = (ParseState * )cpstate ;
11651161
1166- bool has_variable = false;
1162+ node -> has_variable = false;
11671163 if (node -> name )
1168- has_variable = true;
1164+ node -> has_variable = true;
11691165 else
11701166 node -> name = get_next_default_alias (cpstate );
11711167
@@ -1196,9 +1192,9 @@ add_vertex_retrieval_to_query(cypher_parsestate *cpstate, Query *query, cypher_n
11961192{
11971193 ParseState * pstate = (ParseState * )cpstate ;
11981194
1199- bool has_variable = false;
1195+ node -> has_variable = false;
12001196 if (node -> name )
1201- has_variable = true;
1197+ node -> has_variable = true;
12021198 else {
12031199 node -> in_join_tree = false;
12041200 return NULL ;
@@ -1236,10 +1232,9 @@ add_edge_to_query(cypher_parsestate *cpstate, Query *query, cypher_relationship
12361232{
12371233 ParseState * pstate = (ParseState * )cpstate ;
12381234
1235+ edge -> has_variable = false;
12391236 if (edge -> name )
1240- ereport (ERROR ,
1241- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1242- errmsg ("MATCH variable names are not supported" )));
1237+ edge -> has_variable = true;
12431238 else
12441239 edge -> name = get_next_default_alias (cpstate );
12451240
@@ -1266,7 +1261,8 @@ static void add_all_fields_to_target_list(cypher_parsestate *cpstate, Query *que
12661261 ParseState * pstate = (ParseState * )cpstate ;
12671262
12681263 // left vertex id field
1269- query -> targetList = lappend (query -> targetList ,
1264+ if (left_vertex -> in_join_tree ) {
1265+ query -> targetList = lappend (query -> targetList ,
12701266 makeTargetEntry (
12711267 edge -> dir == CYPHER_REL_DIR_RIGHT ?
12721268 scanNSItemForColumn (pstate , left_vertex -> pnsi , 0 , AG_VERTEX_COLNAME_ID , -1 ) :
@@ -1275,22 +1271,24 @@ static void add_all_fields_to_target_list(cypher_parsestate *cpstate, Query *que
12751271 make_id_alias (left_vertex -> name ),
12761272 false));
12771273
1278- // Vertex expression
1279- if (left_vertex -> has_variable ) {
12801274 query -> targetList = lappend (query -> targetList ,
12811275 makeTargetEntry (
12821276 scanNSItemForColumn (pstate , left_vertex -> pnsi , 0 , AG_VERTEX_COLNAME_PROPERTIES , -1 ),
12831277 pstate -> p_next_resno ++ ,
12841278 make_property_alias (left_vertex -> name ),
12851279 false));
1286- /*
1287- query->targetList = lappend(query->targetList,
1288- makeTargetEntry(
1289- (Expr *)make_vertex_expr(cpstate, left_vertex->pnsi),
1290- pstate->p_next_resno++,
1291- left_vertex->name,
1292- false));
1293- */
1280+
1281+ // Vertex expression
1282+ if (left_vertex -> has_variable )
1283+ query -> targetList = lappend (query -> targetList ,
1284+ makeTargetEntry (
1285+ edge -> dir == CYPHER_REL_DIR_LEFT ?
1286+ (Expr * )make_vertex_expr_with_edge (cpstate , left_vertex -> pnsi , edge -> pnsi ) :
1287+ (Expr * )make_vertex_expr (cpstate , left_vertex -> pnsi ),
1288+ pstate -> p_next_resno ++ ,
1289+ left_vertex -> name ,
1290+ false));
1291+
12941292 }
12951293
12961294 // id field
@@ -1326,24 +1324,44 @@ static void add_all_fields_to_target_list(cypher_parsestate *cpstate, Query *que
13261324 false));
13271325
13281326 // id field
1329- query -> targetList = lappend (query -> targetList ,
1327+ if (edge -> has_variable )
1328+ query -> targetList = lappend (query -> targetList ,
1329+ makeTargetEntry (
1330+ (Expr * )make_edge_expr (cpstate , edge -> pnsi ),
1331+ pstate -> p_next_resno ++ ,
1332+ edge -> name ,
1333+ false));
1334+
1335+ // properties field
1336+ if (right_vertex -> in_join_tree ){
1337+ query -> targetList = lappend (query -> targetList ,
13301338 makeTargetEntry (
13311339 edge -> dir == CYPHER_REL_DIR_RIGHT ?
13321340 scanNSItemForColumn (pstate , edge -> pnsi , 0 , AG_EDGE_COLNAME_END_ID , -1 ) :
13331341 scanNSItemForColumn (pstate , right_vertex -> pnsi , 0 , AG_VERTEX_COLNAME_ID , -1 ),
13341342 pstate -> p_next_resno ++ ,
1335- make_id_alias (left_vertex -> name ),
1343+ make_id_alias (right_vertex -> name ),
13361344 false));
13371345
1338- // properties field
1339- if (right_vertex -> in_join_tree )
13401346 query -> targetList = lappend (query -> targetList ,
13411347 makeTargetEntry (
13421348 scanNSItemForColumn (pstate , right_vertex -> pnsi , 0 , AG_VERTEX_COLNAME_PROPERTIES , -1 ),
13431349 pstate -> p_next_resno ++ ,
13441350 make_property_alias (right_vertex -> name ),
13451351 false));
13461352
1353+ // Vertex expression
1354+ if (right_vertex -> has_variable )
1355+ query -> targetList = lappend (query -> targetList ,
1356+ makeTargetEntry (
1357+ edge -> dir == CYPHER_REL_DIR_RIGHT ?
1358+ (Expr * )make_vertex_expr_with_edge (cpstate , right_vertex -> pnsi , edge -> pnsi ) :
1359+ (Expr * )make_vertex_expr (cpstate , right_vertex -> pnsi ),
1360+ pstate -> p_next_resno ++ ,
1361+ right_vertex -> name ,
1362+ false));
1363+ }
1364+
13471365}
13481366
13491367static void transform_match_pattern (cypher_parsestate * cpstate , Query * query , List * pattern , Node * where ) {
@@ -1414,6 +1432,29 @@ static void transform_match_pattern(cypher_parsestate *cpstate, Query *query, Li
14141432
14151433 node -> pnsi = add_vertex_retrieval_to_query (cpstate , query , node , edge -> pnsi );
14161434
1435+ // SELECT fields
1436+ add_all_fields_to_target_list (cpstate ,
1437+ query ,
1438+ (cypher_node * )linitial (path -> path ),
1439+ (cypher_relationship * )lsecond (path -> path ),
1440+ (cypher_node * )lthird (path -> path ));
1441+ } else if ( ((cypher_relationship * )lsecond (path -> path ))-> dir == CYPHER_REL_DIR_LEFT ) {
1442+ ListCell * path_cell ;
1443+
1444+ // left vertex FROM item
1445+ cypher_node * node = lthird (path -> path );
1446+ node -> pnsi = add_vertex_to_query (cpstate , query , node );
1447+
1448+
1449+ // edge FROM item
1450+ cypher_relationship * edge = lsecond (path -> path );
1451+ edge -> pnsi = add_edge_to_query (cpstate , query , edge , node -> pnsi );
1452+
1453+ // right vertex FROM item
1454+ node = linitial (path -> path );
1455+
1456+ node -> pnsi = add_vertex_retrieval_to_query (cpstate , query , node , edge -> pnsi );
1457+
14171458 // SELECT fields
14181459 add_all_fields_to_target_list (cpstate ,
14191460 query ,
0 commit comments