1
1
use num:: Integer ;
2
2
use partiql_ast:: ast;
3
- use partiql_ast:: ast:: { GraphMatchDirection , GraphPathPatternPart } ;
3
+ use partiql_ast:: ast:: { GraphMatchDirection , GraphMatchLabel , GraphMatchPathPattern } ;
4
4
use partiql_logical:: graph:: bind_name:: FreshBinder ;
5
5
use partiql_logical:: graph:: {
6
6
BindSpec , DirectionFilter , EdgeFilter , EdgeMatch , LabelFilter , NodeFilter , NodeMatch ,
7
7
PathMatch , PathPattern , PathPatternMatch , StepFilter , TripleFilter , ValueFilter ,
8
8
} ;
9
+ use petgraph:: visit:: Walker ;
9
10
use std:: mem:: take;
10
11
11
12
#[ macro_export]
@@ -165,94 +166,156 @@ impl GraphToLogical {
165
166
}
166
167
pub ( crate ) fn plan_graph_match (
167
168
& self ,
168
- match_expr : & ast:: GraphMatchExpr ,
169
+ graph_match : & ast:: GraphMatch ,
169
170
) -> Result < PathPatternMatch , String > {
170
- if match_expr. selector . is_some ( ) {
171
- not_yet_implemented_result ! ( "MATCH expression selectors are not yet supported." ) ;
171
+ if graph_match. shape . cols . is_some ( ) {
172
+ not_yet_implemented_result ! ( "MATCH expression COLUMNS are not yet supported." ) ;
173
+ }
174
+ if graph_match. shape . export . is_some ( ) {
175
+ not_yet_implemented_result ! ( "MATCH expression EXPORT are not yet supported." ) ;
176
+ }
177
+ if graph_match. shape . rows . is_some ( ) {
178
+ not_yet_implemented_result ! ( "MATCH expression ROWS are not yet supported." ) ;
179
+ }
180
+
181
+ let pattern = self . plan_graph_pattern ( & graph_match. pattern ) ?;
182
+ let normalized = self . normalize ( pattern) ?;
183
+ let expanded = self . expand ( normalized) ?;
184
+ self . plan ( expanded)
185
+ }
186
+
187
+ fn plan_graph_pattern ( & self , pattern : & ast:: GraphPattern ) -> Result < Vec < MatchElement > , String > {
188
+ if pattern. mode . is_some ( ) {
189
+ not_yet_implemented_result ! ( "MATCH expression MATCH MODE is not yet supported." ) ;
190
+ }
191
+ if pattern. keep . is_some ( ) {
192
+ not_yet_implemented_result ! ( "MATCH expression KEEP is not yet supported." ) ;
193
+ }
194
+ if pattern. where_clause . is_some ( ) {
195
+ not_yet_implemented_result ! ( "MATCH expression WHERE is not yet supported." ) ;
172
196
}
173
197
174
- if match_expr . patterns . len ( ) != 1 {
198
+ if pattern . patterns . len ( ) != 1 {
175
199
not_yet_implemented_result ! (
176
200
"MATCH expression with multiple patterns are not yet supported."
177
201
) ;
178
202
}
179
203
180
- let first_pattern = & match_expr. patterns [ 0 ] . node ;
181
- let pattern = self . plan_graph_pattern ( first_pattern) ?;
182
- let normalized = self . normalize ( pattern) ?;
183
- let expanded = self . expand ( normalized) ?;
184
- self . plan ( expanded)
204
+ let first_pattern = & pattern. patterns [ 0 ] ;
205
+ self . plan_graph_path_pattern ( first_pattern)
185
206
}
186
207
187
- fn plan_graph_pattern (
208
+ fn plan_graph_path_pattern (
188
209
& self ,
189
210
pattern : & ast:: GraphPathPattern ,
190
211
) -> Result < Vec < MatchElement > , String > {
191
- if pattern. restrictor . is_some ( ) {
192
- not_yet_implemented_result ! ( "MATCH pattern restrictors are not yet supported." ) ;
212
+ if pattern. prefix . is_some ( ) {
213
+ not_yet_implemented_result ! ( "MATCH pattern SEARCH/MODE prefix are not yet supported." ) ;
193
214
}
194
- if pattern. quantifier . is_some ( ) {
195
- not_yet_implemented_result ! ( "MATCH pattern quantifiers are not yet supported." ) ;
215
+ if pattern. variable . is_some ( ) {
216
+ not_yet_implemented_result ! ( "MATCH pattern path variables are not yet supported." ) ;
196
217
}
197
- if pattern. prefilter . is_some ( ) {
198
- not_yet_implemented_result ! ( "MATCH pattern prefilters are not yet supported." ) ;
218
+
219
+ self . plan_graph_match_path_pattern ( & pattern. path )
220
+ }
221
+
222
+ fn plan_graph_subpath_pattern (
223
+ & self ,
224
+ pattern : & ast:: GraphPathSubPattern ,
225
+ ) -> Result < Vec < MatchElement > , String > {
226
+ if pattern. mode . is_some ( ) {
227
+ not_yet_implemented_result ! ( "MATCH pattern MODE prefix are not yet supported." ) ;
199
228
}
200
229
if pattern. variable . is_some ( ) {
201
230
not_yet_implemented_result ! ( "MATCH pattern path variables are not yet supported." ) ;
202
231
}
232
+ if pattern. where_clause . is_some ( ) {
233
+ not_yet_implemented_result ! ( "MATCH expression WHERE is not yet supported." ) ;
234
+ }
203
235
204
- let parts = pattern
205
- . parts
206
- . iter ( )
207
- . map ( |p| self . plan_graph_pattern_part ( p) ) ;
208
- let result: Result < Vec < _ > , _ > = parts. collect ( ) ;
209
-
210
- result. map ( |r| r. into_iter ( ) . flatten ( ) . collect ( ) )
236
+ self . plan_graph_match_path_pattern ( & pattern. path )
211
237
}
212
238
213
- fn plan_graph_pattern_part (
239
+ fn plan_graph_match_path_pattern (
214
240
& self ,
215
- part : & ast:: GraphPathPatternPart ,
241
+ pattern : & ast:: GraphMatchPathPattern ,
216
242
) -> Result < Vec < MatchElement > , String > {
217
- match part {
218
- GraphPathPatternPart :: Node ( n) => self . plan_graph_pattern_part_node ( & n. node ) ,
219
- GraphPathPatternPart :: Edge ( e) => self . plan_graph_pattern_part_edge ( & e. node ) ,
220
- GraphPathPatternPart :: Pattern ( pattern) => self . plan_graph_pattern ( & pattern. node ) ,
243
+ match pattern {
244
+ GraphMatchPathPattern :: Path ( path) => {
245
+ let path: Result < Vec < Vec < _ > > , _ > = path
246
+ . iter ( )
247
+ . map ( |elt| self . plan_graph_match_path_pattern ( elt) )
248
+ . collect ( ) ;
249
+ Ok ( path?. into_iter ( ) . flatten ( ) . collect ( ) )
250
+ }
251
+ GraphMatchPathPattern :: Union ( _) => {
252
+ not_yet_implemented_result ! ( "MATCH expression UNION is not yet supported." )
253
+ }
254
+ GraphMatchPathPattern :: Multiset ( _) => {
255
+ not_yet_implemented_result ! ( "MATCH expression MULTISET is not yet supported." )
256
+ }
257
+ GraphMatchPathPattern :: Questioned ( _) => {
258
+ not_yet_implemented_result ! ( "MATCH expression QUESTIONED is not yet supported." )
259
+ }
260
+ GraphMatchPathPattern :: Quantified ( _, _) => {
261
+ not_yet_implemented_result ! ( "MATCH expression QUANTIFIED is not yet supported." )
262
+ }
263
+ GraphMatchPathPattern :: Sub ( subpath) => self . plan_graph_subpath_pattern ( subpath) ,
264
+ GraphMatchPathPattern :: Node ( n) => self . plan_graph_pattern_part_node ( & n) ,
265
+ GraphMatchPathPattern :: Edge ( e) => self . plan_graph_pattern_part_edge ( & e) ,
266
+ GraphMatchPathPattern :: Simplified ( _) => {
267
+ not_yet_implemented_result ! (
268
+ "MATCH expression Simplified Edge Expressions are not yet supported."
269
+ )
270
+ }
221
271
}
222
272
}
223
273
224
274
fn plan_graph_pattern_label (
225
275
& self ,
226
- label : & Option < Vec < ast :: SymbolPrimitive > > ,
276
+ label : Option < & GraphMatchLabel > ,
227
277
) -> Result < LabelFilter , String > {
228
- match label {
229
- None => Ok ( LabelFilter :: Always ) ,
230
- Some ( labels) => {
231
- if labels. len ( ) != 1 {
278
+ if let Some ( label) = label {
279
+ match label {
280
+ GraphMatchLabel :: Name ( n) => Ok ( LabelFilter :: Named ( n. value . clone ( ) ) ) ,
281
+ GraphMatchLabel :: Wildcard => Ok ( LabelFilter :: Always ) ,
282
+ GraphMatchLabel :: Negated ( _) => {
283
+ not_yet_implemented_result ! (
284
+ "MATCH expression label negation is not yet supported."
285
+ ) ;
286
+ }
287
+ GraphMatchLabel :: Conjunction ( _) => {
232
288
not_yet_implemented_result ! (
233
- "MATCH expression with multiple patterns are not yet supported."
289
+ "MATCH expression label conjunction is not yet supported."
290
+ ) ;
291
+ }
292
+ GraphMatchLabel :: Disjunction ( _) => {
293
+ not_yet_implemented_result ! (
294
+ "MATCH expression label disjunction is not yet supported."
234
295
) ;
235
296
}
236
- Ok ( LabelFilter :: Named ( labels[ 0 ] . value . clone ( ) ) )
237
297
}
298
+ } else {
299
+ Ok ( LabelFilter :: Always )
238
300
}
239
301
}
240
302
241
303
fn plan_graph_pattern_part_node (
242
304
& self ,
243
305
node : & ast:: GraphMatchNode ,
244
306
) -> Result < Vec < MatchElement > , String > {
245
- if node. prefilter . is_some ( ) {
246
- not_yet_implemented_result ! ( "MATCH node prefilters are not yet supported." ) ;
307
+ if node. where_clause . is_some ( ) {
308
+ not_yet_implemented_result ! ( "MATCH node where_clauses are not yet supported." ) ;
247
309
}
248
310
let binder = match & node. variable {
249
311
None => self . graph_id . node ( ) ,
250
312
Some ( v) => v. value . clone ( ) ,
251
313
} ;
314
+ let label = self . plan_graph_pattern_label ( node. label . as_deref ( ) ) ?;
252
315
let node_match = NodeMatch {
253
316
binder : BindSpec ( binder) ,
254
317
spec : NodeFilter {
255
- label : self . plan_graph_pattern_label ( & node . label ) ? ,
318
+ label,
256
319
filter : ValueFilter :: Always ,
257
320
} ,
258
321
} ;
@@ -266,8 +329,8 @@ impl GraphToLogical {
266
329
if edge. quantifier . is_some ( ) {
267
330
not_yet_implemented_result ! ( "MATCH edge quantifiers are not yet supported." ) ;
268
331
}
269
- if edge. prefilter . is_some ( ) {
270
- not_yet_implemented_result ! ( "MATCH edge prefilters are not yet supported." ) ;
332
+ if edge. where_clause . is_some ( ) {
333
+ not_yet_implemented_result ! ( "MATCH edge where_clauses are not yet supported." ) ;
271
334
}
272
335
let direction = match & edge. direction {
273
336
GraphMatchDirection :: Left => DirectionFilter :: L ,
@@ -282,10 +345,11 @@ impl GraphToLogical {
282
345
None => self . graph_id . node ( ) ,
283
346
Some ( v) => v. value . clone ( ) ,
284
347
} ;
348
+ let label = self . plan_graph_pattern_label ( edge. label . as_deref ( ) ) ?;
285
349
let edge_match = EdgeMatch {
286
350
binder : BindSpec ( binder) ,
287
351
spec : EdgeFilter {
288
- label : self . plan_graph_pattern_label ( & edge . label ) ? ,
352
+ label,
289
353
filter : ValueFilter :: Always ,
290
354
} ,
291
355
} ;
0 commit comments