11use serde_json:: Value ;
22use std:: cmp:: Ordering ;
3+ use std:: str:: FromStr ;
4+ use jsonpath_rust:: JsonPath ;
35
46#[ derive( Debug , Clone ) ]
57pub enum Expression {
68 FieldReference ( String ) , // dot notation e.g. "a.b"
9+ JsonPath ( String ) , // JSONPath e.g. "$.a.b"
710 Literal ( Value ) ,
811 Binary {
912 left : Box < Expression > ,
@@ -17,16 +20,31 @@ pub enum Expression {
1720 } ,
1821}
1922
20- #[ derive( Debug , Clone ) ]
23+ #[ derive( Debug , Clone , PartialEq ) ]
2124pub enum BinaryOperator {
2225 Eq , Neq , Lt , Lte , Gt , Gte
2326}
2427
25- #[ derive( Debug , Clone ) ]
28+ #[ derive( Debug , Clone , PartialEq ) ]
2629pub enum LogicalOperator {
2730 And , Or
2831}
2932
33+ #[ derive( Debug ) ]
34+ pub enum LogicalPlan {
35+ Scan { collection : String } ,
36+ Filter { input : Box < LogicalPlan > , predicate : Expression } ,
37+ Project { input : Box < LogicalPlan > , projections : Vec < Expression > } ,
38+ Limit { input : Box < LogicalPlan > , limit : usize } ,
39+ Offset { input : Box < LogicalPlan > , offset : usize } ,
40+ }
41+
42+ #[ derive( Debug ) ]
43+ pub enum Statement {
44+ Insert { collection : String , documents : Vec < Value > } ,
45+ Select ( LogicalPlan ) ,
46+ }
47+
3048pub trait QueryOperator {
3149 fn next ( & mut self ) -> Option < ( String , Value ) > ;
3250}
@@ -98,6 +116,9 @@ impl QueryOperator for ProjectOperator {
98116 Expression :: FieldReference ( path) => {
99117 new_doc. insert ( path. clone ( ) , value) ;
100118 }
119+ Expression :: JsonPath ( path) => {
120+ new_doc. insert ( path. clone ( ) , value) ;
121+ }
101122 _ => {
102123 // Fallback/TODO: Handle computed columns alias
103124 }
@@ -165,6 +186,24 @@ fn evaluate_expression(expr: &Expression, doc: &Value) -> Value {
165186 Expression :: FieldReference ( path) => {
166187 get_path ( doc, path) . unwrap_or ( Value :: Null )
167188 }
189+ Expression :: JsonPath ( path) => {
190+ if let Ok ( p) = JsonPath :: from_str ( path) {
191+ let inst = p. find ( doc) ;
192+ if let Some ( arr) = inst. as_array ( ) {
193+ if arr. is_empty ( ) {
194+ Value :: Null
195+ } else if arr. len ( ) == 1 {
196+ arr[ 0 ] . clone ( )
197+ } else {
198+ inst. clone ( )
199+ }
200+ } else {
201+ inst
202+ }
203+ } else {
204+ Value :: Null
205+ }
206+ }
168207 Expression :: Literal ( val) => val. clone ( ) ,
169208 Expression :: Binary { left, op, right } => {
170209 let l_val = evaluate_expression ( left, doc) ;
@@ -298,6 +337,28 @@ mod tests {
298337 assert ! ( filter. next( ) . is_none( ) ) ;
299338 }
300339
340+ #[ test]
341+ fn test_jsonpath ( ) {
342+ let data = vec ! [
343+ ( "1" . to_string( ) , json!( { "a" : { "b" : 10 } } ) ) ,
344+ ( "2" . to_string( ) , json!( { "a" : { "b" : 20 } } ) ) ,
345+ ] ;
346+ let source = Box :: new ( MockSource :: new ( data) ) ;
347+
348+ // Filter: $.a.b > 15
349+ let predicate = Expression :: Binary {
350+ left : Box :: new ( Expression :: JsonPath ( "$.a.b" . to_string ( ) ) ) ,
351+ op : BinaryOperator :: Gt ,
352+ right : Box :: new ( Expression :: Literal ( json ! ( 15 ) ) ) ,
353+ } ;
354+
355+ let mut filter = FilterOperator :: new ( source, predicate) ;
356+
357+ let ( id, _) = filter. next ( ) . unwrap ( ) ;
358+ assert_eq ! ( id, "2" ) ;
359+ assert ! ( filter. next( ) . is_none( ) ) ;
360+ }
361+
301362 #[ test]
302363 fn test_project ( ) {
303364 let data = vec ! [
0 commit comments