8000 Merge pull request #2 from protodef/pattern · filiprem/postgres@6c87d04 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6c87d04

Browse files
author
Kisung Kim
committed
Merge pull request postgres#2 from protodef/pattern
feat(cypher): Implement pattern grammar
2 parents a307376 + 8c6104d commit 6c87d04

File tree

6 files changed

+184
-11
lines changed

6 files changed

+184
-11
lines changed

src/backend/nodes/copyfuncs.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4166,6 +4166,20 @@ _copyCypherNode(const CypherNode *from)
41664166
return newnode;
41674167
}
41684168

4169+
static CypherRel *
4170+
_copyCypherRel(const CypherRel *from)
4171+
{
4172+
CypherRel *newnode = makeNode(CypherRel);
4173+
4174+
COPY_SCALAR_FIELD(direction);
4175+
COPY_STRING_FIELD(variable);
4176+
COPY_NODE_FIELD(types);
4177+
COPY_NODE_FIELD(varlen);
4178+
COPY_STRING_FIELD(prop_map);
4179+
4180+
return newnode;
4181+
}
4182+
41694183
/* ****************************************************************
41704184
* pg_list.h copy functions
41714185
* ****************************************************************
@@ -5043,6 +5057,9 @@ copyObject(const void *from)
50435057
case T_CypherNode:
50445058
retval = _copyCypherNode(from);
50455059
break;
5060+
case T_CypherRel:
5061+
retval = _copyCypherRel(from);
5062+
break;
50465063

50475064
default:
50485065
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(from));

src/backend/nodes/equalfuncs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,6 +2615,18 @@ _equalCypherNode(const CypherNode *a, const CypherNode *b)
26152615
return true;
26162616
}
26172617

2618+
static bool
2619+
_equalCypherRel(const CypherRel *a, const CypherRel *b)
2620+
{
2621+
COMPARE_SCALAR_FIELD(direction);
2622+
COMPARE_STRING_FIELD(variable);
2623+
COMPARE_NODE_FIELD(types);
2624+
COMPARE_NODE_FIELD(varlen);
2625+
COMPARE_STRING_FIELD(prop_map);
2626+
2627+
return true;
2628+
}
2629+
26182630
/*
26192631
* Stuff from pg_list.h
26202632
*/
@@ -3370,6 +3382,9 @@ equal(const void *a, const void *b)
33703382
case T_CypherNode:
33713383
retval = _equalCypherNode(a, b);
33723384
break;
3385+
case T_CypherRel:
3386+
retval = _equalCypherRel(a, b);
3387+
break;
33733388

33743389
default:
33753390
elog(ERROR, "unrecognized node type: %d",

src/backend/nodes/outfuncs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3002,6 +3002,18 @@ _outCypherNode(StringInfo str, const CypherNode *node)
30023002
WRITE_STRING_FIELD(prop_map);
30033003
}
30043004

3005+
static void
3006+
_outCypherRel(StringInfo str, const CypherRel *node)
3007+
{
3008+
WRITE_NODE_TYPE("CYPHERREL");
3009+
3010+
WRITE_INT_FIELD(direction);
3011+
WRITE_STRING_FIELD(variable);
3012+
WRITE_NODE_FIELD(types);
3013+
WRITE_NODE_FIELD(varlen);
3014+
WRITE_STRING_FIELD(prop_map);
3015+
}
3016+
30053017
/*
30063018
* _outNode -
30073019
* converts a Node into ascii string and append it to 'str'
@@ -3547,6 +3559,9 @@ _outNode(StringInfo str, const void *obj)
35473559
case T_CypherNode:
35483560
_outCypherNode(str, obj);
35493561
break;
3562+
case T_CypherRel:
3563+
_outCypherRel(str, obj);
3564+
break;
35503565

35513566
default:
35523567

src/backend/parser/gram.y

Lines changed: 122 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,13 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
540540
%type <boolean> opt_if_not_exists
541541

542542
%type <node> CypherStmt cypher_clause cypher_clause_sub cypher_match
543-
cypher_no_parens cypher_node cypher_pattern cypher_return
544-
cypher_with_parens
545-
%type <list> cypher_pattern_list
543+
cypher_no_parens cypher_node cypher_pattern cypher_range_idx
544+
cypher_range_idx_opt cypher_range_opt cypher_rel cypher_return
545+
cypher_varlen_opt cypher_with_parens
546+
%type <list> cypher_pattern_chain cypher_pattern_list cypher_types
547+
cypher_types_opt
546548
%type <str> cypher_label_opt cypher_prop_map_opt cypher_variable_opt
549+
%type <boolean> cypher_rel_left cypher_rel_right
547550

548551
/*
549552
* Non-keyword token types. These are hard-wired into the "flex" lexer.
@@ -14194,14 +14197,21 @@ cypher_pattern_list:
1419414197
;
1419514198

1419614199
cypher_pattern:
14197-
cypher_node
14200+
cypher_pattern_chain
1419814201
{
1419914202
CypherPattern *n = makeNode(CypherPattern);
14200-
n->chain = list_make1($1);
14203+
n->chain = $1;
1420114204
$$ = (Node *) n;
1420214205
}
1420314206
;
1420414207

14208+
cypher_pattern_chain:
14209+
cypher_node
14210+
{ $$ = list_make1($1); }
14211+
| cypher_pattern_chain cypher_rel cypher_node
14212+
{ $$ = lappend(lappend($1, $2), $3); }
14213+
;
14214+
1420514215
cypher_node:
1420614216
'(' cypher_variable_opt cypher_label_opt cypher_prop_map_opt ')'
1420714217
{
@@ -14214,18 +14224,119 @@ cypher_node:
1421414224
;
1421514225

1421614226
cypher_variable_opt:
14217-
ColId
14218-
| /* EMPTY */ { $$ = NULL; }
14227+
ColLabel
14228+
| /* EMPTY */ { $$ = NULL; }
1421914229
;
1422014230

1422114231
cypher_label_opt:
14222-
':' ColId { $$ = $2; }
14223-
| /* EMPTY */ { $$ = NULL; }
14232+
':' ColId { $$ = $2; }
14233+
| /* EMPTY */ { $$ = NULL; }
1422414234
;
1422514235

1422614236
cypher_prop_map_opt:
14227-
SCONST
14228-
| /* EMTPY */ { $$ = NULL; }
14237+
Sconst
14238+
| /* EMTPY */ { $$ = NULL; }
14239+
;
14240+
14241+
cypher_rel:
14242+
cypher_rel_left '[' cypher_variable_opt
14243+
cypher_types_opt cypher_varlen_opt cypher_prop_map_opt
14244+
']' cypher_rel_right
14245+
{
14246+
CypherRel *n = makeNode(CypherRel);
14247+
if ($1)
14248+
n->direction |= CYPHER_REL_DIR_LEFT;
14249+
if ($8)
14250+
n->direction |= CYPHER_REL_DIR_RIGHT;
14251+
if ($1 && $8)
14252+
n->direction = CYPHER_REL_DIR_NONE;
14253+
n->variable = $3;
14254+
n->types = $4;
14255+
n->varlen = $5;
14256+
n->prop_map = $6;
14257+
$$ = (Node *) n;
14258+
}
14259+
;
14260+
14261+
cypher_rel_left:
14262+
'-' { $$ = false; }
14263+
| '<' '-' { $$ = true; }
14264+
;
14265+
14266+
cypher_rel_right:
14267+
'-'
14268+
{ $$ = false; }
14269+
| Op
14270+
{
14271+
/*
14272+
* This is tricky but the scanner treats -> as an operator.
14273+
*/
14274+
if (strcmp($1, "->") != 0)
14275+
ereport(ERROR,
14276+
(errcode(ERRCODE_SYNTAX_ERROR),
14277+
errmsg("syntax error: -> expected"),
14278+
parser_errposition(@1)));
14279+
$$ = tru E377 e;
14280+
}
14281+
;
14282+
14283+
cypher_types_opt:
14284+
cypher_types
14285+
| /* EMPTY */ { $$ = NIL; }
14286+
;
14287+
14288+
cypher_types:
14289+
':' ColId
14290+
{ $$ = list_make1(makeString($2)); }
14291+
| cypher_types Op ColId
14292+
{
14293+
/* this is also tricky */
14294+
if (strcmp($2, "|") != 0)
14295+
ereport(ERROR,
14296+
(errcode(ERRCODE_SYNTAX_ERROR),
14297+
errmsg("syntax error: | expected"),
14298+
parser_errposition(@2)));
14299+
$$ = lappend($1, makeString($3));
14300+
}
14301+
;
14302+
14303+
cypher_varlen_opt:
14304+
'*' cypher_range_opt
14305+
{
14306+
if ($2 == NULL)
14307+
$2 = (Node *) makeNode(A_Indices);
14308+
$$ = $2;
14309+
}
14310+
| /* EMPTY */
14311+
{ $$ = NULL; }
14312+
;
14313+
14314+
cypher_range_opt:
14315+
cypher_range_idx
14316+
{
14317+
A_Indices *n = makeNode(A_Indices);
14318+
n->lidx = copyObject($1);
14319+
n->uidx = $1;
14320+
$$ = (Node *) n;
14321+
}
14322+
| cypher_range_idx_opt DOT_DOT cypher_range_idx_opt
14323+
{
14324+
A_Indices *n = makeNode(A_Indices);
14325+
n->lidx = $1;
14326+
n->uidx = $3;
14327+
$$ = (Node *) n;
14328+
}
14329+
| /* EMPTY */
14330+
{ $$ = NULL; }
14331+
;
14332+
14333+
cypher_range_idx_opt:
14334+
cypher_range_idx
14335+
| /* EMPTY */ { $$ = NULL; }
14336+
;
14337+
14338+
cypher_range_idx:
14339+
Iconst { $$ = makeIntConst($1, @1); }
1422914340
;
1423014341

1423114342
%%

src/include/nodes/nodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ typedef enum NodeTag
432432
T_CypherReturnClause,
433433
T_CypherPattern,
434434
T_CypherNode,
435+
T_CypherRel,
435436

436437
/*
437438
* TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)

src/include/nodes/parsenodes.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3116,4 +3116,18 @@ typedef struct CypherNode
31163116
char *prop_map; /* JSON object string */
31173117
} CypherNode;
31183118

3119+
#define CYPHER_REL_DIR_NONE 0
3120+
#define CYPHER_REL_DIR_LEFT (1 << 0)
3121+
#define CYPHER_REL_DIR_RIGHT (1 << 1)
3122+
3123+
typedef struct CypherRel
3124+
{
3125+
NodeTag type;
3126+
uint32 direction; /* bitmask of directions (see above) */
3127+
char *variable;
3128+
List *types; /* ORed types */
3129+
Node *varlen; /* variable length relationships (A_Indices) */
3130+
char *prop_map; /* JSON object string */
3131+
} CypherRel;
3132+
31193133
#endif /* PARSENODES_H */

0 commit comments

Comments
 (0)
0