Skip to main content

aurora_db/parser/
mod.rs

1//! Aurora Query Language (AQL) Parser
2//!
3//! Provides parsing for AQL using Pest grammar.
4
5use pest::Parser;
6use pest_derive::Parser;
7
8pub mod ast;
9pub mod executor;
10pub mod validator;
11
12#[derive(Parser)]
13#[grammar = "parser/grammar.pest"]
14pub struct AQLParser;
15
16use crate::error::{AqlError, ErrorCode, Result};
17use ast::*;
18use serde_json::Value as JsonValue;
19use std::collections::HashMap;
20
21/// Parse an AQL query string into an AST Document
22pub fn parse(input: &str) -> Result<Document> {
23    let pairs = AQLParser::parse(Rule::document, input)
24        .map_err(|e| AqlError::new(ErrorCode::ProtocolError, format!("Parse error: {}", e)))?;
25
26    let mut operations = Vec::new();
27
28    for pair in pairs {
29        if pair.as_rule() == Rule::document {
30            for inner in pair.into_inner() {
31                match inner.as_rule() {
32                    Rule::operation => {
33                        if let Some(op) = parse_operation(inner)? {
34                            operations.push(op);
35                        }
36                    }
37                    Rule::fragment_definition => {
38                        operations.push(Operation::FragmentDefinition(parse_fragment_definition(
39                            inner,
40                        )?));
41                    }
42                    _ => {}
43                }
44            }
45        }
46    }
47
48    Ok(Document { operations })
49}
50
51/// Parse an AQL query with variable values
52pub fn parse_with_variables(input: &str, variables: JsonValue) -> Result<Document> {
53    let mut doc = parse(input)?;
54
55    let vars: HashMap<String, Value> = if let JsonValue::Object(map) = variables {
56        map.into_iter()
57            .map(|(k, v)| (k, json_to_aql_value(v)))
58            .collect()
59    } else {
60        HashMap::new()
61    };
62
63    if let Some(op) = doc.operations.first_mut() {
64        match op {
65            Operation::Query(q) => q.variables_values = vars,
66            Operation::Mutation(m) => m.variables_values = vars,
67            Operation::Subscription(s) => s.variables_values = vars,
68            _ => {}
69        }
70    }
71
72    Ok(doc)
73}
74
75fn json_to_aql_value(json: JsonValue) -> Value {
76    match json {
77        JsonValue::Null => Value::Null,
78        JsonValue::Bool(b) => Value::Boolean(b),
79        JsonValue::Number(n) => {
80            if let Some(i) = n.as_i64() {
81                Value::Int(i)
82            } else if let Some(f) = n.as_f64() {
83                Value::Float(f)
84            } else {
85                Value::Null
86            }
87        }
88        JsonValue::String(s) => Value::String(s),
89        JsonValue::Array(arr) => Value::Array(arr.into_iter().map(json_to_aql_value).collect()),
90        JsonValue::Object(map) => Value::Object(
91            map.into_iter()
92                .map(|(k, v)| (k, json_to_aql_value(v)))
93                .collect(),
94        ),
95    }
96}
97
98fn parse_operation(pair: pest::iterators::Pair<Rule>) -> Result<Option<Operation>> {
99    match pair.as_rule() {
100        Rule::operation => {
101            for inner in pair.into_inner() {
102                return parse_operation(inner);
103            }
104            Ok(None)
105        }
106        Rule::query_operation => Ok(Some(Operation::Query(parse_query(pair)?))),
107        Rule::mutation_operation => Ok(Some(Operation::Mutation(parse_mutation(pair)?))),
108        Rule::subscription_operation => {
109            Ok(Some(Operation::Subscription(parse_subscription(pair)?)))
110        }
111        Rule::schema_operation => Ok(Some(Operation::Schema(parse_schema(pair)?))),
112        Rule::migration_operation => Ok(Some(Operation::Migration(parse_migration(pair)?))),
113        Rule::introspection_query => Ok(Some(Operation::Introspection(parse_introspection_query(
114            pair,
115        )?))),
116        Rule::EOI => Ok(None),
117        _ => Ok(None),
118    }
119}
120
121fn parse_query(pair: pest::iterators::Pair<Rule>) -> Result<Query> {
122    let mut name = None;
123    let mut variable_definitions = Vec::new();
124    let mut directives = Vec::new();
125    let mut selection_set = Vec::new();
126
127    for inner in pair.into_inner() {
128        match inner.as_rule() {
129            Rule::identifier => name = Some(inner.as_str().to_string()),
130            Rule::variable_definitions => variable_definitions = parse_variable_definitions(inner)?,
131            Rule::directives => directives = parse_directives(inner)?,
132            Rule::selection_set => selection_set = parse_selection_set(inner)?,
133            _ => {}
134        }
135    }
136
137    Ok(Query {
138        name,
139        variable_definitions,
140        directives,
141        selection_set,
142        variables_values: HashMap::new(),
143    })
144}
145
146fn parse_mutation(pair: pest::iterators::Pair<Rule>) -> Result<Mutation> {
147    let mut name = None;
148    let mut variable_definitions = Vec::new();
149    let mut directives = Vec::new();
150    let mut operations = Vec::new();
151
152    for inner in pair.into_inner() {
153        match inner.as_rule() {
154            Rule::identifier => name = Some(inner.as_str().to_string()),
155            Rule::variable_definitions => variable_definitions = parse_variable_definitions(inner)?,
156            Rule::directives => directives = parse_directives(inner)?,
157            Rule::mutation_set => operations = parse_mutation_set(inner)?,
158            _ => {}
159        }
160    }
161
162    Ok(Mutation {
163        name,
164        variable_definitions,
165        directives,
166        operations,
167        variables_values: HashMap::new(),
168    })
169}
170
171fn parse_subscription(pair: pest::iterators::Pair<Rule>) -> Result<Subscription> {
172    let mut name = None;
173    let mut variable_definitions = Vec::new();
174    let mut directives = Vec::new();
175    let mut selection_set = Vec::new();
176
177    for inner in pair.into_inner() {
178        match inner.as_rule() {
179            Rule::identifier => name = Some(inner.as_str().to_string()),
180            Rule::variable_definitions => variable_definitions = parse_variable_definitions(inner)?,
181            Rule::directives => directives = parse_directives(inner)?,
182            Rule::subscription_set => selection_set = parse_subscription_set(inner)?,
183            _ => {}
184        }
185    }
186
187    Ok(Subscription {
188        name,
189        variable_definitions,
190        directives,
191        selection_set,
192        variables_values: HashMap::new(),
193    })
194}
195
196fn parse_schema(pair: pest::iterators::Pair<Rule>) -> Result<Schema> {
197    let mut operations = Vec::new();
198    for inner in pair.into_inner() {
199        if inner.as_rule() == Rule::schema_definition {
200            for rule in inner.into_inner() {
201                match rule.as_rule() {
202                    Rule::define_collection => operations.push(parse_define_collection(rule)?),
203                    Rule::alter_collection => operations.push(parse_alter_collection(rule)?),
204                    Rule::drop_collection => operations.push(parse_drop_collection(rule)?),
205                    _ => {}
206                }
207            }
208        }
209    }
210    Ok(Schema { operations })
211}
212
213fn parse_define_collection(pair: pest::iterators::Pair<Rule>) -> Result<SchemaOp> {
214    let mut name = String::new();
215    let mut if_not_exists = false;
216    let mut fields = Vec::new();
217    let mut directives = Vec::new();
218
219    for inner in pair.into_inner() {
220        match inner.as_rule() {
221            Rule::identifier => name = inner.as_str().to_string(),
222            Rule::field_definition => fields.push(parse_field_definition(inner)?),
223            Rule::directives => directives = parse_directives(inner)?,
224            _ => {
225                if inner.as_str() == "if" {
226                    // Crude check, relying on grammar structure
227                    if_not_exists = true;
228                }
229            }
230        }
231    }
232    Ok(SchemaOp::DefineCollection {
233        name,
234        if_not_exists,
235        fields,
236        directives,
237    })
238}
239
240fn parse_alter_collection(pair: pest::iterators::Pair<Rule>) -> Result<SchemaOp> {
241    let mut name = String::new();
242    let mut actions = Vec::new();
243
244    for inner in pair.into_inner() {
245        match inner.as_rule() {
246            Rule::identifier => name = inner.as_str().to_string(),
247            Rule::alter_action => actions.push(parse_alter_action(inner)?),
248            _ => {}
249        }
250    }
251    Ok(SchemaOp::AlterCollection { name, actions })
252}
253
254fn parse_alter_action(pair: pest::iterators::Pair<Rule>) -> Result<AlterAction> {
255    let input_str = pair.as_str().to_string();
256    for inner in pair.into_inner() {
257        match inner.as_rule() {
258            Rule::add_action => {
259                for field in inner.into_inner() {
260                    if field.as_rule() == Rule::field_definition {
261                        return Ok(AlterAction::AddField(parse_field_definition(field)?));
262                    }
263                }
264            }
265            Rule::drop_action => {
266                for id in inner.into_inner() {
267                    if id.as_rule() == Rule::identifier {
268                        return Ok(AlterAction::DropField(id.as_str().to_string()));
269                    }
270                }
271            }
272            Rule::rename_action => {
273                let mut ids = Vec::new();
274                for id in inner.into_inner() {
275                    if id.as_rule() == Rule::identifier {
276                        ids.push(id.as_str().to_string());
277                    }
278                }
279                if ids.len() == 2 {
280                    return Ok(AlterAction::RenameField {
281                        from: ids[0].clone(),
282                        to: ids[1].clone(),
283                    });
284                }
285            }
286            Rule::modify_action => {
287                for field in inner.into_inner() {
288                    if field.as_rule() == Rule::field_definition {
289                        return Ok(AlterAction::ModifyField(parse_field_definition(field)?));
290                    }
291                }
292            }
293            _ => {}
294        }
295    }
296
297    Err(AqlError::new(
298        ErrorCode::ProtocolError,
299        format!("Unknown alter action: {}", input_str),
300    ))
301}
302
303// Re-implementing correctly below with keyword checking
304fn parse_drop_collection(pair: pest::iterators::Pair<Rule>) -> Result<SchemaOp> {
305    let mut name = String::new();
306    let mut if_exists = false;
307
308    for inner in pair.into_inner() {
309        match inner.as_rule() {
310            Rule::identifier => name = inner.as_str().to_string(),
311            _ => {
312                if inner.as_str() == "if" {
313                    if_exists = true;
314                }
315            }
316        }
317    }
318    Ok(SchemaOp::DropCollection { name, if_exists })
319}
320
321fn parse_field_definition(pair: pest::iterators::Pair<Rule>) -> Result<FieldDef> {
322    let mut name = String::new();
323    let mut field_type = TypeAnnotation {
324        name: "String".to_string(),
325        is_array: false,
326        is_required: false,
327    };
328    let mut directives = Vec::new();
329
330    for inner in pair.into_inner() {
331        match inner.as_rule() {
332            Rule::identifier => name = inner.as_str().to_string(),
333            Rule::type_annotation => field_type = parse_type_annotation(inner)?,
334            Rule::directives => directives = parse_directives(inner)?,
335            _ => {}
336        }
337    }
338
339    Ok(FieldDef {
340        name,
341        field_type,
342        directives,
343    })
344}
345
346// MIGRATION PARSING
347
348fn parse_migration(pair: pest::iterators::Pair<Rule>) -> Result<Migration> {
349    let mut steps = Vec::new();
350    for inner in pair.into_inner() {
351        if inner.as_rule() == Rule::migration_step {
352            steps.push(parse_migration_step(inner)?);
353        }
354    }
355    Ok(Migration { steps })
356}
357
358fn parse_migration_step(pair: pest::iterators::Pair<Rule>) -> Result<MigrationStep> {
359    let mut version = String::new();
360    let mut actions = Vec::new();
361
362    for inner in pair.into_inner() {
363        match inner.as_rule() {
364            Rule::migration_version => {
365                // migration_version -> string
366                if let Some(s_pair) = inner.into_inner().next() {
367                    // Strip quotes
368                    let s = s_pair.as_str();
369                    version = s[1..s.len() - 1].to_string();
370                }
371            }
372            Rule::migration_action => {
373                for act in inner.into_inner() {
374                    match act.as_rule() {
375                        Rule::define_collection => {
376                            actions.push(MigrationAction::Schema(parse_define_collection(act)?))
377                        }
378                        Rule::alter_collection => {
379                            actions.push(MigrationAction::Schema(parse_alter_collection(act)?))
380                        }
381                        Rule::drop_collection => {
382                            actions.push(MigrationAction::Schema(parse_drop_collection(act)?))
383                        }
384                        Rule::data_migration => {
385                            actions.push(MigrationAction::DataMigration(parse_data_migration(act)?))
386                        }
387                        _ => {}
388                    }
389                }
390            }
391            _ => {}
392        }
393    }
394    Ok(MigrationStep { version, actions })
395}
396
397fn parse_data_migration(pair: pest::iterators::Pair<Rule>) -> Result<DataMigration> {
398    let mut collection = String::new();
399    let mut transforms = Vec::new();
400
401    for inner in pair.into_inner() {
402        match inner.as_rule() {
403            Rule::identifier => collection = inner.as_str().to_string(),
404            Rule::data_transform => transforms.push(parse_data_transform(inner)?),
405            _ => {}
406        }
407    }
408    Ok(DataMigration {
409        collection,
410        transforms,
411    })
412}
413
414fn parse_data_transform(pair: pest::iterators::Pair<Rule>) -> Result<DataTransform> {
415    let mut field = String::new();
416    let mut expression = String::new();
417    let mut filter = None;
418
419    for inner in pair.into_inner() {
420        match inner.as_rule() {
421            Rule::identifier => field = inner.as_str().to_string(),
422            Rule::expression => expression = inner.as_str().to_string(),
423            Rule::filter_object => {
424                // Parse filter_object to Value then convert to Filter
425                if let Ok(filter_value) = parse_filter_object_to_value(inner) {
426                    filter = value_to_filter(filter_value).ok();
427                }
428            }
429            _ => {}
430        }
431    }
432    Ok(DataTransform {
433        field,
434        expression,
435        filter,
436    })
437}
438
439/// Parse a filter_object grammar rule to an AST Value
440fn parse_filter_object_to_value(pair: pest::iterators::Pair<Rule>) -> Result<Value> {
441    let mut map = HashMap::new();
442
443    for inner in pair.into_inner() {
444        if inner.as_rule() == Rule::filter_field_list {
445            for filter_field in inner.into_inner() {
446                if filter_field.as_rule() == Rule::filter_field {
447                    parse_filter_field_to_map(filter_field, &mut map)?;
448                }
449            }
450        }
451    }
452
453    Ok(Value::Object(map))
454}
455
456/// Parse a filter_field into the map
457fn parse_filter_field_to_map(
458    pair: pest::iterators::Pair<Rule>,
459    map: &mut HashMap<String, Value>,
460) -> Result<()> {
461    for inner in pair.into_inner() {
462        match inner.as_rule() {
463            Rule::logical_operator => {
464                parse_logical_operator_to_map(inner, map)?;
465            }
466            Rule::field_filter | Rule::nested_field_filter => {
467                let mut field_name = String::new();
468                let mut field_ops = HashMap::new();
469
470                for field_inner in inner.into_inner() {
471                    match field_inner.as_rule() {
472                        Rule::identifier => field_name = field_inner.as_str().to_string(),
473                        Rule::string => {
474                            let s = field_inner.as_str();
475                            field_name = s[1..s.len() - 1].to_string();
476                        }
477                        Rule::filter_condition => {
478                            parse_filter_condition_to_map(field_inner, &mut field_ops)?;
479                        }
480                        _ => {}
481                    }
482                }
483
484                if !field_name.is_empty() {
485                    map.insert(field_name, Value::Object(field_ops));
486                }
487            }
488            _ => {}
489        }
490    }
491    Ok(())
492}
493
494/// Parse a logical operator (and/or/not) into the map
495fn parse_logical_operator_to_map(
496    pair: pest::iterators::Pair<Rule>,
497    map: &mut HashMap<String, Value>,
498) -> Result<()> {
499    for inner in pair.into_inner() {
500        match inner.as_rule() {
501            Rule::and_operator => {
502                let mut filters = Vec::new();
503                for and_inner in inner.into_inner() {
504                    if and_inner.as_rule() == Rule::filter_object {
505                        filters.push(parse_filter_object_to_value(and_inner)?);
506                    }
507                }
508                map.insert("and".to_string(), Value::Array(filters));
509            }
510            Rule::or_operator => {
511                let mut filters = Vec::new();
512                for or_inner in inner.into_inner() {
513                    if or_inner.as_rule() == Rule::filter_object {
514                        filters.push(parse_filter_object_to_value(or_inner)?);
515                    }
516                }
517                map.insert("or".to_string(), Value::Array(filters));
518            }
519            Rule::not_operator => {
520                for not_inner in inner.into_inner() {
521                    if not_inner.as_rule() == Rule::filter_object {
522                        map.insert("not".to_string(), parse_filter_object_to_value(not_inner)?);
523                    }
524                }
525            }
526            _ => {}
527        }
528    }
529    Ok(())
530}
531
532/// Parse a filter_condition into the map
533fn parse_filter_condition_to_map(
534    pair: pest::iterators::Pair<Rule>,
535    map: &mut HashMap<String, Value>,
536) -> Result<()> {
537    for inner in pair.into_inner() {
538        if inner.as_rule() == Rule::filter_operator_list {
539            for op in inner.into_inner() {
540                if op.as_rule() == Rule::filter_operator {
541                    parse_filter_operator_to_map(op, map)?;
542                }
543            }
544        }
545    }
546    Ok(())
547}
548
549/// Parse a filter_operator into the map
550fn parse_filter_operator_to_map(
551    pair: pest::iterators::Pair<Rule>,
552    map: &mut HashMap<String, Value>,
553) -> Result<()> {
554    for inner in pair.into_inner() {
555        match inner.as_rule() {
556            Rule::eq_operator => {
557                for val in inner.into_inner() {
558                    if val.as_rule() == Rule::value {
559                        map.insert("eq".to_string(), parse_value(val)?);
560                    }
561                }
562            }
563            Rule::ne_operator => {
564                for val in inner.into_inner() {
565                    if val.as_rule() == Rule::value {
566                        map.insert("ne".to_string(), parse_value(val)?);
567                    }
568                }
569            }
570            Rule::gt_operator => {
571                for val in inner.into_inner() {
572                    if val.as_rule() == Rule::value {
573                        map.insert("gt".to_string(), parse_value(val)?);
574                    }
575                }
576            }
577            Rule::gte_operator => {
578                for val in inner.into_inner() {
579                    if val.as_rule() == Rule::value {
580                        map.insert("gte".to_string(), parse_value(val)?);
581                    }
582                }
583            }
584            Rule::lt_operator => {
585                for val in inner.into_inner() {
586                    if val.as_rule() == Rule::value {
587                        map.insert("lt".to_string(), parse_value(val)?);
588                    }
589                }
590            }
591            Rule::lte_operator => {
592                for val in inner.into_inner() {
593                    if val.as_rule() == Rule::value {
594                        map.insert("lte".to_string(), parse_value(val)?);
595                    }
596                }
597            }
598            Rule::in_operator => {
599                for val in inner.into_inner() {
600                    if val.as_rule() == Rule::array {
601                        map.insert("in".to_string(), parse_value(val)?);
602                    }
603                }
604            }
605            Rule::nin_operator => {
606                for val in inner.into_inner() {
607                    if val.as_rule() == Rule::array {
608                        map.insert("nin".to_string(), parse_value(val)?);
609                    }
610                }
611            }
612            Rule::contains_operator => {
613                for val in inner.into_inner() {
614                    if val.as_rule() == Rule::value {
615                        map.insert("contains".to_string(), parse_value(val)?);
616                    }
617                }
618            }
619            Rule::starts_with_operator => {
620                for val in inner.into_inner() {
621                    if val.as_rule() == Rule::value {
622                        map.insert("startsWith".to_string(), parse_value(val)?);
623                    }
624                }
625            }
626            Rule::ends_with_operator => {
627                for val in inner.into_inner() {
628                    if val.as_rule() == Rule::value {
629                        map.insert("endsWith".to_string(), parse_value(val)?);
630                    }
631                }
632            }
633            Rule::is_null_operator => {
634                map.insert("isNull".to_string(), Value::Boolean(true));
635            }
636            Rule::is_not_null_operator => {
637                map.insert("isNotNull".to_string(), Value::Boolean(true));
638            }
639            _ => {}
640        }
641    }
642    Ok(())
643}
644
645fn parse_variable_definitions(
646    pair: pest::iterators::Pair<Rule>,
647) -> Result<Vec<VariableDefinition>> {
648    let mut definitions = Vec::new();
649    for inner in pair.into_inner() {
650        if inner.as_rule() == Rule::variable_definition {
651            definitions.push(parse_variable_definition(inner)?);
652        }
653    }
654    Ok(definitions)
655}
656
657fn parse_variable_definition(pair: pest::iterators::Pair<Rule>) -> Result<VariableDefinition> {
658    let mut name = String::new();
659    let mut var_type = TypeAnnotation {
660        name: "String".to_string(),
661        is_array: false,
662        is_required: false,
663    };
664    let mut default_value = None;
665
666    for inner in pair.into_inner() {
667        match inner.as_rule() {
668            Rule::variable => name = inner.as_str().trim_start_matches('$').to_string(),
669            Rule::type_annotation => var_type = parse_type_annotation(inner)?,
670            Rule::default_value => {
671                for val in inner.into_inner() {
672                    if val.as_rule() == Rule::value {
673                        default_value = Some(parse_value(val)?);
674                    }
675                }
676            }
677            _ => {}
678        }
679    }
680
681    Ok(VariableDefinition {
682        name,
683        var_type,
684        default_value,
685    })
686}
687
688fn parse_type_annotation(pair: pest::iterators::Pair<Rule>) -> Result<TypeAnnotation> {
689    let mut name = String::new();
690    let mut is_array = false;
691    let mut is_required = false;
692
693    for inner in pair.into_inner() {
694        match inner.as_rule() {
695            Rule::type_name => name = inner.as_str().to_string(),
696            Rule::array_type => {
697                is_array = true;
698                for arr_inner in inner.into_inner() {
699                    if arr_inner.as_rule() == Rule::type_annotation {
700                        let inner_type = parse_type_annotation(arr_inner)?;
701                        name = inner_type.name;
702                    }
703                }
704            }
705            Rule::type_modifier => is_required = true,
706            _ => name = inner.as_str().to_string(),
707        }
708    }
709
710    Ok(TypeAnnotation {
711        name,
712        is_array,
713        is_required,
714    })
715}
716
717fn parse_directives(pair: pest::iterators::Pair<Rule>) -> Result<Vec<Directive>> {
718    let mut directives = Vec::new();
719    for inner in pair.into_inner() {
720        if inner.as_rule() == Rule::directive {
721            directives.push(parse_directive(inner)?);
722        }
723    }
724    Ok(directives)
725}
726
727fn parse_directive(pair: pest::iterators::Pair<Rule>) -> Result<Directive> {
728    let mut name = String::new();
729    let mut arguments = Vec::new();
730
731    for inner in pair.into_inner() {
732        match inner.as_rule() {
733            Rule::directive_name | Rule::identifier => name = inner.as_str().to_string(),
734            Rule::arguments => arguments = parse_arguments(inner)?,
735            _ => {}
736        }
737    }
738
739    Ok(Directive { name, arguments })
740}
741
742fn parse_selection_set(pair: pest::iterators::Pair<Rule>) -> Result<Vec<Field>> {
743    let mut fields = Vec::new();
744    for inner in pair.into_inner() {
745        if inner.as_rule() == Rule::field {
746            fields.push(parse_field(inner)?);
747        }
748    }
749    Ok(fields)
750}
751
752fn parse_subscription_set(pair: pest::iterators::Pair<Rule>) -> Result<Vec<Field>> {
753    let mut fields = Vec::new();
754    for inner in pair.into_inner() {
755        if inner.as_rule() == Rule::subscription_field {
756            fields.push(parse_field(inner)?);
757        }
758    }
759    Ok(fields)
760}
761
762fn parse_field(pair: pest::iterators::Pair<Rule>) -> Result<Field> {
763    let mut alias = None;
764    let mut name = String::new();
765    let mut arguments = Vec::new();
766    let mut directives = Vec::new();
767    let mut selection_set = Vec::new();
768
769    for inner in pair.into_inner() {
770        match inner.as_rule() {
771            Rule::alias_name => {
772                for alias_inner in inner.into_inner() {
773                    if alias_inner.as_rule() == Rule::identifier {
774                        alias = Some(alias_inner.as_str().to_string());
775                    }
776                }
777            }
778            Rule::identifier => name = inner.as_str().to_string(),
779            Rule::arguments => arguments = parse_arguments(inner)?,
780            Rule::directives => directives = parse_directives(inner)?,
781            Rule::sub_selection => {
782                for sel in inner.into_inner() {
783                    if sel.as_rule() == Rule::selection_set {
784                        selection_set = parse_selection_set(sel)?;
785                    }
786                }
787            }
788            Rule::fragment_spread => {
789                name = format!("...{}", inner.as_str().trim_start_matches("...").trim());
790            }
791            Rule::aggregate_with_alias => {
792                // Parse: alias_name? ~ "aggregate" ~ "{" ~ aggregate_field_list ~ "}"
793                name = "aggregate".to_string();
794                for sel in inner.into_inner() {
795                    match sel.as_rule() {
796                        Rule::alias_name => {
797                            for alias_inner in sel.into_inner() {
798                                if alias_inner.as_rule() == Rule::identifier {
799                                    alias = Some(alias_inner.as_str().to_string());
800                                }
801                            }
802                        }
803                        Rule::aggregate_field_list => {
804                            for agg_field in sel.into_inner() {
805                                if agg_field.as_rule() == Rule::aggregate_field {
806                                    selection_set.push(parse_aggregate_field(agg_field)?);
807                                }
808                            }
809                        }
810                        _ => {}
811                    }
812                }
813            }
814            Rule::special_field_selection => {
815                // Handle special selections like groupBy, lookup, etc. (aggregate is handled separately)
816                for sel in inner.into_inner() {
817                    match sel.as_rule() {
818                        Rule::alias_name => {
819                            for alias_inner in sel.into_inner() {
820                                if alias_inner.as_rule() == Rule::identifier {
821                                    alias = Some(alias_inner.as_str().to_string());
822                                }
823                            }
824                        }
825                        Rule::group_by_selection => {
826                            name = "groupBy".to_string();
827                        }
828                        Rule::lookup_selection => {
829                            name = "lookup".to_string();
830                            // Use parse_lookup_selection and convert to Field arguments
831                            let lookup = parse_lookup_selection(sel)?;
832                            arguments.push(ast::Argument {
833                                name: "collection".to_string(),
834                                value: ast::Value::String(lookup.collection),
835                            });
836                            arguments.push(ast::Argument {
837                                name: "localField".to_string(),
838                                value: ast::Value::String(lookup.local_field),
839                            });
840                            arguments.push(ast::Argument {
841                                name: "foreignField".to_string(),
842                                value: ast::Value::String(lookup.foreign_field),
843                            });
844                            if let Some(filter) = lookup.filter {
845                                arguments.push(ast::Argument {
846                                    name: "where".to_string(),
847                                    value: filter_to_value(&filter),
848                                });
849                            }
850                            // Convert Selection back to Field for selection_set
851                            selection_set = lookup.selection_set.into_iter().filter_map(|s| {
852                                if let ast::Selection::Field(f) = s { Some(f) } else { None }
853                            }).collect();
854                        }
855                        Rule::page_info_selection => {
856                            name = "pageInfo".to_string();
857                        }
858                        Rule::edges_selection => {
859                            name = "edges".to_string();
860                            // Parse edge_fields and add to selection_set
861                            for edge_inner in sel.into_inner() {
862                                if edge_inner.as_rule() == Rule::edge_fields {
863                                    for edge_field in edge_inner.into_inner() {
864                                        if edge_field.as_rule() == Rule::edge_field {
865                                            let edge_str = edge_field.as_str().trim();
866                                            if edge_str.starts_with("cursor") {
867                                                selection_set.push(Field {
868                                                    alias: None,
869                                                    name: "cursor".to_string(),
870                                                    arguments: Vec::new(),
871                                                    directives: Vec::new(),
872                                                    selection_set: Vec::new(),
873                                                });
874                                            } else if edge_str.starts_with("node") {
875                                                // Parse node's selection set
876                                                let mut node_selection = Vec::new();
877                                                for node_inner in edge_field.into_inner() {
878                                                    if node_inner.as_rule() == Rule::selection_set {
879                                                        node_selection =
880                                                            parse_selection_set(node_inner)?;
881                                                    }
882                                                }
883                                                selection_set.push(Field {
884                                                    alias: None,
885                                                    name: "node".to_string(),
886                                                    arguments: Vec::new(),
887                                                    directives: Vec::new(),
888                                                    selection_set: node_selection,
889                                                });
890                                            }
891                                        }
892                                    }
893                                }
894                            }
895                        }
896                        Rule::downsample_selection => {
897                            name = "downsample".to_string();
898                        }
899                        _ => {}
900                    }
901                }
902            }
903            _ => {}
904        }
905    }
906
907    Ok(Field {
908        alias,
909        name,
910        arguments,
911        directives,
912        selection_set,
913    })
914}
915
916/// Parse an aggregate field (count or function like sum(field: "x"))
917/// Supports optional aliases like `totalStock: sum(field: "stock")`
918fn parse_aggregate_field(pair: pest::iterators::Pair<Rule>) -> Result<Field> {
919    let mut name = String::new();
920    let mut alias = None;
921    let mut arguments = Vec::new();
922    let pair_str = pair.as_str().to_string();
923
924    for inner in pair.into_inner() {
925        match inner.as_rule() {
926            Rule::aggregate_field_alias => {
927                // Extract alias from aggregate_field_alias (contains identifier ~ ":")
928                for alias_inner in inner.into_inner() {
929                    if alias_inner.as_rule() == Rule::identifier {
930                        alias = Some(alias_inner.as_str().to_string());
931                    }
932                }
933            }
934            Rule::aggregate_field_value => {
935                // Contains either "count" or aggregate_function
936                let inner_str = inner.as_str().to_string();
937                for val_inner in inner.into_inner() {
938                    match val_inner.as_rule() {
939                        Rule::aggregate_function => {
940                            // Parse function like sum(field: "age")
941                            for fn_inner in val_inner.into_inner() {
942                                match fn_inner.as_rule() {
943                                    Rule::aggregate_name => {
944                                        name = fn_inner.as_str().to_string();
945                                    }
946                                    Rule::aggregate_args => {
947                                        // Parse field: "name" or fields: [...]
948                                        let mut arg_name = String::new();
949                                        let mut arg_value = Value::Null;
950
951                                        for arg_inner in fn_inner.into_inner() {
952                                            match arg_inner.as_rule() {
953                                                Rule::string => {
954                                                    let s = arg_inner.as_str();
955                                                    arg_value = Value::String(
956                                                        s[1..s.len() - 1].to_string(),
957                                                    );
958                                                    if arg_name.is_empty() {
959                                                        arg_name = "field".to_string();
960                                                    }
961                                                }
962                                                Rule::array => {
963                                                    arg_value = parse_value(arg_inner)?;
964                                                    arg_name = "fields".to_string();
965                                                }
966                                                _ => {
967                                                    // Check for "field" or "fields" keyword
968                                                    let text = arg_inner.as_str();
969                                                    if text == "field" || text == "fields" {
970                                                        arg_name = text.to_string();
971                                                    }
972                                                }
973                                            }
974                                        }
975
976                                        if !arg_name.is_empty() && !matches!(arg_value, Value::Null)
977                                        {
978                                            arguments.push(Argument {
979                                                name: arg_name,
980                                                value: arg_value,
981                                            });
982                                        }
983                                    }
984                                    _ => {}
985                                }
986                            }
987                        }
988                        _ => {
989                            // Should be "count" literal
990                        }
991                    }
992                }
993
994                // If no aggregate_function found, check if it's "count" literal
995                if name.is_empty() {
996                    let text = inner_str.trim();
997                    if text == "count" {
998                        name = "count".to_string();
999                    }
1000                }
1001            }
1002            _ => {}
1003        }
1004    }
1005
1006    // Fallback: If name is still empty but the raw text contains "count"
1007    if name.is_empty() {
1008        let text = pair_str.trim();
1009        if text == "count" || text.ends_with(": count") || text.contains("count") {
1010            name = "count".to_string();
1011        }
1012    }
1013
1014    Ok(Field {
1015        alias,
1016        name,
1017        arguments,
1018        directives: vec![],
1019        selection_set: vec![],
1020    })
1021}
1022
1023fn parse_mutation_set(pair: pest::iterators::Pair<Rule>) -> Result<Vec<MutationOperation>> {
1024    let mut operations = Vec::new();
1025    for inner in pair.into_inner() {
1026        if inner.as_rule() == Rule::mutation_field {
1027            operations.push(parse_mutation_field(inner)?);
1028        }
1029    }
1030    Ok(operations)
1031}
1032
1033fn parse_mutation_field(pair: pest::iterators::Pair<Rule>) -> Result<MutationOperation> {
1034    let mut alias = None;
1035    let mut operation = MutationOp::Insert {
1036        collection: String::new(),
1037        data: Value::Null,
1038    };
1039    let mut directives = Vec::new();
1040    let mut selection_set = Vec::new();
1041
1042    for inner in pair.into_inner() {
1043        match inner.as_rule() {
1044            Rule::alias_name => {
1045                for alias_inner in inner.into_inner() {
1046                    if alias_inner.as_rule() == Rule::identifier {
1047                        alias = Some(alias_inner.as_str().to_string());
1048                    }
1049                }
1050            }
1051            Rule::mutation_call => {
1052                let (op, sel) = parse_mutation_call(inner)?;
1053                operation = op;
1054                selection_set = sel;
1055            }
1056            Rule::directives => directives = parse_directives(inner)?,
1057            _ => {}
1058        }
1059    }
1060
1061    Ok(MutationOperation {
1062        alias,
1063        operation,
1064        directives,
1065        selection_set,
1066    })
1067}
1068
1069fn parse_mutation_call(pair: pest::iterators::Pair<Rule>) -> Result<(MutationOp, Vec<Field>)> {
1070    for inner in pair.into_inner() {
1071        match inner.as_rule() {
1072            Rule::insert_mutation => return parse_insert_mutation(inner),
1073            Rule::update_mutation => return parse_update_mutation(inner),
1074            Rule::delete_mutation => return parse_delete_mutation(inner),
1075            Rule::enqueue_job_mutation => return parse_enqueue_job_mutation(inner),
1076            Rule::transaction_block => return parse_transaction_block(inner),
1077            _ => {}
1078        }
1079    }
1080    Err(AqlError::new(
1081        ErrorCode::ProtocolError,
1082        "Unknown mutation type".to_string(),
1083    ))
1084}
1085
1086fn parse_insert_mutation(pair: pest::iterators::Pair<Rule>) -> Result<(MutationOp, Vec<Field>)> {
1087    let mut collection = String::new();
1088    let mut data = Value::Null;
1089    let mut selection_set = Vec::new();
1090
1091    for inner in pair.into_inner() {
1092        match inner.as_rule() {
1093            Rule::insert_args => {
1094                for arg in parse_arguments_list(inner)? {
1095                    match arg.name.as_str() {
1096                        "collection" => {
1097                            if let Value::String(s) = arg.value {
1098                                collection = s;
1099                            }
1100                        }
1101                        "data" => data = arg.value,
1102                        _ => {}
1103                    }
1104                }
1105            }
1106            Rule::sub_selection => {
1107                for sel in inner.into_inner() {
1108                    if sel.as_rule() == Rule::selection_set {
1109                        selection_set = parse_selection_set(sel)?;
1110                    }
1111                }
1112            }
1113            _ => {}
1114        }
1115    }
1116
1117    Ok((MutationOp::Insert { collection, data }, selection_set))
1118}
1119
1120fn parse_update_mutation(pair: pest::iterators::Pair<Rule>) -> Result<(MutationOp, Vec<Field>)> {
1121    let mut collection = String::new();
1122    let mut filter = None;
1123    let mut data = Value::Null;
1124    let mut selection_set = Vec::new();
1125
1126    for inner in pair.into_inner() {
1127        match inner.as_rule() {
1128            Rule::update_args => {
1129                for arg in parse_arguments_list(inner)? {
1130                    match arg.name.as_str() {
1131                        "collection" => {
1132                            if let Value::String(s) = arg.value {
1133                                collection = s;
1134                            }
1135                        }
1136                        "where" => filter = Some(value_to_filter(arg.value)?),
1137                        "data" => data = arg.value,
1138                        _ => {}
1139                    }
1140                }
1141            }
1142            Rule::sub_selection => {
1143                for sel in inner.into_inner() {
1144                    if sel.as_rule() == Rule::selection_set {
1145                        selection_set = parse_selection_set(sel)?;
1146                    }
1147                }
1148            }
1149            _ => {}
1150        }
1151    }
1152
1153    Ok((
1154        MutationOp::Update {
1155            collection,
1156            filter,
1157            data,
1158        },
1159        selection_set,
1160    ))
1161}
1162
1163fn parse_delete_mutation(pair: pest::iterators::Pair<Rule>) -> Result<(MutationOp, Vec<Field>)> {
1164    let mut collection = String::new();
1165    let mut filter = None;
1166    let mut selection_set = Vec::new();
1167
1168    for inner in pair.into_inner() {
1169        match inner.as_rule() {
1170            Rule::delete_args => {
1171                for arg in parse_arguments_list(inner)? {
1172                    match arg.name.as_str() {
1173                        "collection" => {
1174                            if let Value::String(s) = arg.value {
1175                                collection = s;
1176                            }
1177                        }
1178                        "where" => filter = Some(value_to_filter(arg.value)?),
1179                        _ => {}
1180                    }
1181                }
1182            }
1183            Rule::sub_selection => {
1184                for sel in inner.into_inner() {
1185                    if sel.as_rule() == Rule::selection_set {
1186                        selection_set = parse_selection_set(sel)?;
1187                    }
1188                }
1189            }
1190            _ => {}
1191        }
1192    }
1193
1194    Ok((MutationOp::Delete { collection, filter }, selection_set))
1195}
1196
1197fn parse_enqueue_job_mutation(
1198    pair: pest::iterators::Pair<Rule>,
1199) -> Result<(MutationOp, Vec<Field>)> {
1200    let mut job_type = String::new();
1201    let mut payload = Value::Null;
1202    let mut priority = JobPriority::Normal;
1203    let mut scheduled_at = None;
1204    let mut max_retries = None;
1205    let mut selection_set = Vec::new();
1206
1207    for inner in pair.into_inner() {
1208        match inner.as_rule() {
1209            Rule::job_args => {
1210                for arg in parse_arguments_list(inner)? {
1211                    match arg.name.as_str() {
1212                        "jobType" => {
1213                            if let Value::String(s) = arg.value {
1214                                job_type = s;
1215                            }
1216                        }
1217                        "payload" => payload = arg.value,
1218                        "priority" => {
1219                            if let Value::Enum(s) = arg.value {
1220                                priority = match s.as_str() {
1221                                    "LOW" => JobPriority::Low,
1222                                    "HIGH" => JobPriority::High,
1223                                    "CRITICAL" => JobPriority::Critical,
1224                                    _ => JobPriority::Normal,
1225                                };
1226                            }
1227                        }
1228                        "scheduledAt" => {
1229                            if let Value::String(s) = arg.value {
1230                                scheduled_at = Some(s);
1231                            }
1232                        }
1233                        "maxRetries" => {
1234                            if let Value::Int(n) = arg.value {
1235                                max_retries = Some(n as u32);
1236                            }
1237                        }
1238                        _ => {}
1239                    }
1240                }
1241            }
1242            Rule::sub_selection => {
1243                for sel in inner.into_inner() {
1244                    if sel.as_rule() == Rule::selection_set {
1245                        selection_set = parse_selection_set(sel)?;
1246                    }
1247                }
1248            }
1249            _ => {}
1250        }
1251    }
1252
1253    Ok((
1254        MutationOp::EnqueueJob {
1255            job_type,
1256            payload,
1257            priority,
1258            scheduled_at,
1259            max_retries,
1260        },
1261        selection_set,
1262    ))
1263}
1264
1265fn parse_transaction_block(pair: pest::iterators::Pair<Rule>) -> Result<(MutationOp, Vec<Field>)> {
1266    let mut operations = Vec::new();
1267    for inner in pair.into_inner() {
1268        if inner.as_rule() == Rule::mutation_set {
1269            operations = parse_mutation_set(inner)?;
1270        }
1271    }
1272    Ok((MutationOp::Transaction { operations }, Vec::new()))
1273}
1274
1275fn parse_arguments(pair: pest::iterators::Pair<Rule>) -> Result<Vec<Argument>> {
1276    let mut arguments = Vec::new();
1277    for inner in pair.into_inner() {
1278        match inner.as_rule() {
1279            Rule::argument_list => {
1280                for arg in inner.into_inner() {
1281                    if arg.as_rule() == Rule::argument {
1282                        arguments.push(parse_argument(arg)?);
1283                    }
1284                }
1285            }
1286            Rule::argument => arguments.push(parse_argument(inner)?),
1287            _ => {}
1288        }
1289    }
1290    Ok(arguments)
1291}
1292
1293fn parse_arguments_list(pair: pest::iterators::Pair<Rule>) -> Result<Vec<Argument>> {
1294    let mut arguments = Vec::new();
1295    for inner in pair.into_inner() {
1296        if inner.as_rule() == Rule::argument {
1297            arguments.push(parse_argument(inner)?);
1298        }
1299    }
1300    Ok(arguments)
1301}
1302
1303fn parse_argument(pair: pest::iterators::Pair<Rule>) -> Result<Argument> {
1304    let mut name = String::new();
1305    let mut value = Value::Null;
1306
1307    for inner in pair.into_inner() {
1308        match inner.as_rule() {
1309            Rule::identifier => name = inner.as_str().to_string(),
1310            Rule::value => value = parse_value(inner)?,
1311            _ => {}
1312        }
1313    }
1314
1315    Ok(Argument { name, value })
1316}
1317
1318fn parse_value(pair: pest::iterators::Pair<Rule>) -> Result<Value> {
1319    match pair.as_rule() {
1320        Rule::value => {
1321            for inner in pair.into_inner() {
1322                return parse_value(inner);
1323            }
1324            Ok(Value::Null)
1325        }
1326        Rule::string => {
1327            let s = pair.as_str();
1328            let unquoted = if s.starts_with("\"\"\"") {
1329                &s[3..s.len() - 3]
1330            } else {
1331                &s[1..s.len() - 1]
1332            };
1333            Ok(Value::String(unquoted.to_string()))
1334        }
1335        Rule::number => {
1336            let s = pair.as_str();
1337            if s.contains('.') || s.contains('e') || s.contains('E') {
1338                Ok(Value::Float(s.parse().unwrap_or(0.0)))
1339            } else {
1340                Ok(Value::Int(s.parse().unwrap_or(0)))
1341            }
1342        }
1343        Rule::boolean => Ok(Value::Boolean(pair.as_str() == "true")),
1344        Rule::null => Ok(Value::Null),
1345        Rule::variable => Ok(Value::Variable(
1346            pair.as_str().trim_start_matches('$').to_string(),
1347        )),
1348        Rule::enum_value => Ok(Value::Enum(pair.as_str().to_string())),
1349        Rule::array => {
1350            let mut values = Vec::new();
1351            for inner in pair.into_inner() {
1352                if inner.as_rule() == Rule::array_value_list {
1353                    for val in inner.into_inner() {
1354                        if val.as_rule() == Rule::value {
1355                            values.push(parse_value(val)?);
1356                        }
1357                    }
1358                }
1359            }
1360            Ok(Value::Array(values))
1361        }
1362        Rule::object => {
1363            let mut map = HashMap::new();
1364            for inner in pair.into_inner() {
1365                if inner.as_rule() == Rule::object_field_list {
1366                    for field in inner.into_inner() {
1367                        if field.as_rule() == Rule::object_field {
1368                            let (key, val) = parse_object_field(field)?;
1369                            map.insert(key, val);
1370                        }
1371                    }
1372                }
1373            }
1374            Ok(Value::Object(map))
1375        }
1376        _ => Ok(Value::Null),
1377    }
1378}
1379
1380fn parse_object_field(pair: pest::iterators::Pair<Rule>) -> Result<(String, Value)> {
1381    let mut key = String::new();
1382    let mut value = Value::Null;
1383
1384    for inner in pair.into_inner() {
1385        match inner.as_rule() {
1386            Rule::identifier => key = inner.as_str().to_string(),
1387            Rule::string => {
1388                let s = inner.as_str();
1389                key = s[1..s.len() - 1].to_string();
1390            }
1391            Rule::value => value = parse_value(inner)?,
1392            _ => {}
1393        }
1394    }
1395
1396    Ok((key, value))
1397}
1398
1399fn value_to_filter(value: Value) -> Result<Filter> {
1400    match value {
1401        Value::Object(map) => {
1402            let mut filters = Vec::new();
1403            for (key, val) in map {
1404                match key.as_str() {
1405                    "and" => {
1406                        if let Value::Array(arr) = val {
1407                            let sub: Result<Vec<_>> =
1408                                arr.into_iter().map(value_to_filter).collect();
1409                            filters.push(Filter::And(sub?));
1410                        }
1411                    }
1412                    "or" => {
1413                        if let Value::Array(arr) = val {
1414                            let sub: Result<Vec<_>> =
1415                                arr.into_iter().map(value_to_filter).collect();
1416                            filters.push(Filter::Or(sub?));
1417                        }
1418                    }
1419                    "not" => filters.push(Filter::Not(Box::new(value_to_filter(val)?))),
1420                    field => {
1421                        if let Value::Object(ops) = val {
1422                            for (op, op_val) in ops {
1423                                let f = match op.as_str() {
1424                                    "eq" => Filter::Eq(field.to_string(), op_val),
1425                                    "ne" => Filter::Ne(field.to_string(), op_val),
1426                                    "gt" => Filter::Gt(field.to_string(), op_val),
1427                                    "gte" => Filter::Gte(field.to_string(), op_val),
1428                                    "lt" => Filter::Lt(field.to_string(), op_val),
1429                                    "lte" => Filter::Lte(field.to_string(), op_val),
1430                                    "in" => Filter::In(field.to_string(), op_val),
1431                                    "nin" => Filter::NotIn(field.to_string(), op_val),
1432                                    "contains" => Filter::Contains(field.to_string(), op_val),
1433                                    "startsWith" => Filter::StartsWith(field.to_string(), op_val),
1434                                    "endsWith" => Filter::EndsWith(field.to_string(), op_val),
1435                                    "isNull" => Filter::IsNull(field.to_string()),
1436                                    "isNotNull" => Filter::IsNotNull(field.to_string()),
1437                                    _ => continue,
1438                                };
1439                                filters.push(f);
1440                            }
1441                        }
1442                    }
1443                }
1444            }
1445            if filters.len() == 1 {
1446                Ok(filters.remove(0))
1447            } else {
1448                Ok(Filter::And(filters))
1449            }
1450        }
1451        _ => Err(AqlError::new(
1452            ErrorCode::ProtocolError,
1453            "Filter must be an object".to_string(),
1454        )),
1455    }
1456}
1457
1458/// Convert Filter back to Value (reverse of value_to_filter)
1459fn filter_to_value(filter: &Filter) -> Value {
1460    use std::collections::HashMap;
1461    match filter {
1462        Filter::Eq(field, val) => {
1463            let mut inner = HashMap::new();
1464            inner.insert("eq".to_string(), val.clone());
1465            let mut outer = HashMap::new();
1466            outer.insert(field.clone(), Value::Object(inner));
1467            Value::Object(outer)
1468        }
1469        Filter::Ne(field, val) => {
1470            let mut inner = HashMap::new();
1471            inner.insert("ne".to_string(), val.clone());
1472            let mut outer = HashMap::new();
1473            outer.insert(field.clone(), Value::Object(inner));
1474            Value::Object(outer)
1475        }
1476        Filter::Gt(field, val) => {
1477            let mut inner = HashMap::new();
1478            inner.insert("gt".to_string(), val.clone());
1479            let mut outer = HashMap::new();
1480            outer.insert(field.clone(), Value::Object(inner));
1481            Value::Object(outer)
1482        }
1483        Filter::Gte(field, val) => {
1484            let mut inner = HashMap::new();
1485            inner.insert("gte".to_string(), val.clone());
1486            let mut outer = HashMap::new();
1487            outer.insert(field.clone(), Value::Object(inner));
1488            Value::Object(outer)
1489        }
1490        Filter::Lt(field, val) => {
1491            let mut inner = HashMap::new();
1492            inner.insert("lt".to_string(), val.clone());
1493            let mut outer = HashMap::new();
1494            outer.insert(field.clone(), Value::Object(inner));
1495            Value::Object(outer)
1496        }
1497        Filter::Lte(field, val) => {
1498            let mut inner = HashMap::new();
1499            inner.insert("lte".to_string(), val.clone());
1500            let mut outer = HashMap::new();
1501            outer.insert(field.clone(), Value::Object(inner));
1502            Value::Object(outer)
1503        }
1504        Filter::In(field, val) => {
1505            let mut inner = HashMap::new();
1506            inner.insert("in".to_string(), val.clone());
1507            let mut outer = HashMap::new();
1508            outer.insert(field.clone(), Value::Object(inner));
1509            Value::Object(outer)
1510        }
1511        Filter::NotIn(field, val) => {
1512            let mut inner = HashMap::new();
1513            inner.insert("nin".to_string(), val.clone());
1514            let mut outer = HashMap::new();
1515            outer.insert(field.clone(), Value::Object(inner));
1516            Value::Object(outer)
1517        }
1518        Filter::Contains(field, val) => {
1519            let mut inner = HashMap::new();
1520            inner.insert("contains".to_string(), val.clone());
1521            let mut outer = HashMap::new();
1522            outer.insert(field.clone(), Value::Object(inner));
1523            Value::Object(outer)
1524        }
1525        Filter::StartsWith(field, val) => {
1526            let mut inner = HashMap::new();
1527            inner.insert("startsWith".to_string(), val.clone());
1528            let mut outer = HashMap::new();
1529            outer.insert(field.clone(), Value::Object(inner));
1530            Value::Object(outer)
1531        }
1532        Filter::EndsWith(field, val) => {
1533            let mut inner = HashMap::new();
1534            inner.insert("endsWith".to_string(), val.clone());
1535            let mut outer = HashMap::new();
1536            outer.insert(field.clone(), Value::Object(inner));
1537            Value::Object(outer)
1538        }
1539        Filter::Matches(field, val) => {
1540            let mut inner = HashMap::new();
1541            inner.insert("matches".to_string(), val.clone());
1542            let mut outer = HashMap::new();
1543            outer.insert(field.clone(), Value::Object(inner));
1544            Value::Object(outer)
1545        }
1546        Filter::IsNull(field) => {
1547            let mut inner = HashMap::new();
1548            inner.insert("isNull".to_string(), Value::Boolean(true));
1549            let mut outer = HashMap::new();
1550            outer.insert(field.clone(), Value::Object(inner));
1551            Value::Object(outer)
1552        }
1553        Filter::IsNotNull(field) => {
1554            let mut inner = HashMap::new();
1555            inner.insert("isNotNull".to_string(), Value::Boolean(true));
1556            let mut outer = HashMap::new();
1557            outer.insert(field.clone(), Value::Object(inner));
1558            Value::Object(outer)
1559        }
1560        Filter::And(filters) => {
1561            let arr: Vec<Value> = filters.iter().map(filter_to_value).collect();
1562            let mut map = HashMap::new();
1563            map.insert("and".to_string(), Value::Array(arr));
1564            Value::Object(map)
1565        }
1566        Filter::Or(filters) => {
1567            let arr: Vec<Value> = filters.iter().map(filter_to_value).collect();
1568            let mut map = HashMap::new();
1569            map.insert("or".to_string(), Value::Array(arr));
1570            Value::Object(map)
1571        }
1572        Filter::Not(inner) => {
1573            let mut map = HashMap::new();
1574            map.insert("not".to_string(), filter_to_value(inner));
1575            Value::Object(map)
1576        }
1577    }
1578}
1579
1580// FRAGMENT AND INTROSPECTION PARSING
1581fn parse_fragment_definition(pair: pest::iterators::Pair<Rule>) -> Result<ast::FragmentDef> {
1582    let mut name = String::new();
1583    let mut type_condition = String::new();
1584    let mut selection_set = Vec::new();
1585
1586    for inner in pair.into_inner() {
1587        match inner.as_rule() {
1588            Rule::identifier => {
1589                if name.is_empty() {
1590                    name = inner.as_str().to_string();
1591                } else {
1592                    type_condition = inner.as_str().to_string();
1593                }
1594            }
1595            Rule::selection_set => {
1596                // Convert Vec<Field> to Vec<Selection>
1597                let fields = parse_selection_set(inner)?;
1598                selection_set = fields.into_iter().map(ast::Selection::Field).collect();
1599            }
1600            _ => {}
1601        }
1602    }
1603
1604    Ok(ast::FragmentDef {
1605        name,
1606        type_condition,
1607        selection_set,
1608    })
1609}
1610
1611fn parse_introspection_query(pair: pest::iterators::Pair<Rule>) -> Result<ast::IntrospectionQuery> {
1612    let mut arguments = Vec::new();
1613    let mut fields = Vec::new();
1614
1615    for inner in pair.into_inner() {
1616        match inner.as_rule() {
1617            Rule::arguments => {
1618                arguments = parse_arguments(inner)?;
1619            }
1620            Rule::introspection_fields => {
1621                for field in inner.into_inner() {
1622                    if field.as_rule() == Rule::introspection_field {
1623                        fields.push(field.as_str().to_string());
1624                    }
1625                }
1626            }
1627            _ => {}
1628        }
1629    }
1630
1631    Ok(ast::IntrospectionQuery { arguments, fields })
1632}
1633
1634fn parse_lookup_selection(pair: pest::iterators::Pair<Rule>) -> Result<ast::LookupSelection> {
1635    let mut collection = String::new();
1636    let mut local_field = String::new();
1637    let mut foreign_field = String::new();
1638    let mut filter = None;
1639    let mut selection_set = Vec::new();
1640
1641    for inner in pair.into_inner() {
1642        match inner.as_rule() {
1643            Rule::lookup_args => {
1644                for arg in inner.into_inner() {
1645                    match arg.as_rule() {
1646                        Rule::string => {
1647                            let s = arg.as_str();
1648                            let unquoted = &s[1..s.len() - 1];
1649                            if collection.is_empty() {
1650                                collection = unquoted.to_string();
1651                            } else if local_field.is_empty() {
1652                                local_field = unquoted.to_string();
1653                            } else if foreign_field.is_empty() {
1654                                foreign_field = unquoted.to_string();
1655                            }
1656                        }
1657                        Rule::filter_object => {
1658                            if let Ok(filter_value) = parse_filter_object_to_value(arg) {
1659                                filter = value_to_filter(filter_value).ok();
1660                            }
1661                        }
1662                        _ => {}
1663                    }
1664                }
1665            }
1666            Rule::sub_selection => {
1667                for sel in inner.into_inner() {
1668                    if sel.as_rule() == Rule::selection_set {
1669                        let fields = parse_selection_set(sel)?;
1670                        selection_set = fields.into_iter().map(ast::Selection::Field).collect();
1671                    }
1672                }
1673            }
1674            _ => {}
1675        }
1676    }
1677
1678    Ok(ast::LookupSelection {
1679        collection,
1680        local_field,
1681        foreign_field,
1682        filter,
1683        selection_set,
1684    })
1685}
1686
1687#[cfg(test)]
1688mod tests {
1689    use super::*;
1690
1691    #[test]
1692    fn test_parse_simple_query() {
1693        let query = r#"query { users { id name email } }"#;
1694        let result = parse(query);
1695        assert!(result.is_ok());
1696        let doc = result.unwrap();
1697        assert_eq!(doc.operations.len(), 1);
1698    }
1699
1700    #[test]
1701    fn test_parse_query_with_filter() {
1702        let query =
1703            r#"query GetActiveUsers { users(where: { active: { eq: true } }) { id name } }"#;
1704        let result = parse(query);
1705        assert!(result.is_ok());
1706    }
1707
1708    #[test]
1709    fn test_parse_mutation() {
1710        let query =
1711            r#"mutation { insertInto(collection: "users", data: { name: "John" }) { id } }"#;
1712        let result = parse(query);
1713        assert!(result.is_ok());
1714    }
1715
1716    #[test]
1717    fn test_parse_alter_collection() {
1718        let schema = r#"
1719            schema {
1720                 alter collection users {
1721                     add age: Int
1722                     drop legacy_field
1723                     rename name to full_name
1724                     modify active: Boolean
1725                 }
1726            }
1727        "#;
1728        let result = parse(schema);
1729        assert!(
1730            result.is_ok(),
1731            "Failed to parse alter collection: {:?}",
1732            result.err()
1733        );
1734
1735        let doc = result.unwrap();
1736        if let Operation::Schema(Schema { operations }) = &doc.operations[0] {
1737            if let SchemaOp::AlterCollection { name, actions } = &operations[0] {
1738                assert_eq!(name, "users");
1739                assert_eq!(actions.len(), 4);
1740
1741                // Check add action
1742                match &actions[0] {
1743                    AlterAction::AddField(field) => {
1744                        assert_eq!(field.name, "age");
1745                        assert_eq!(field.field_type.name, "Int");
1746                    }
1747                    _ => panic!("Expected AddField"),
1748                }
1749
1750                // Check drop action
1751                match &actions[1] {
1752                    AlterAction::DropField(name) => assert_eq!(name, "legacy_field"),
1753                    _ => panic!("Expected DropField"),
1754                }
1755
1756                // Check rename action
1757                match &actions[2] {
1758                    AlterAction::RenameField { from, to } => {
1759                        assert_eq!(from, "name");
1760                        assert_eq!(to, "full_name");
1761                    }
1762                    _ => panic!("Expected RenameField"),
1763                }
1764
1765                // Check modify action
1766                match &actions[3] {
1767                    AlterAction::ModifyField(field) => {
1768                        assert_eq!(field.name, "active");
1769                        assert_eq!(field.field_type.name, "Boolean");
1770                    }
1771                    _ => panic!("Expected ModifyField"),
1772                }
1773            } else {
1774                panic!("Expected AlterCollection operation");
1775            }
1776        } else {
1777            panic!("Expected Schema operation");
1778        }
1779    }
1780
1781    #[test]
1782    fn test_parse_fragment_definition() {
1783        let query = r#"
1784            fragment UserFields on User {
1785                id
1786                name
1787                email
1788            }
1789        "#;
1790        let result = parse(query);
1791        assert!(
1792            result.is_ok(),
1793            "Failed to parse fragment: {:?}",
1794            result.err()
1795        );
1796        let doc = result.unwrap();
1797        assert_eq!(doc.operations.len(), 1);
1798
1799        if let Operation::FragmentDefinition(frag) = &doc.operations[0] {
1800            assert_eq!(frag.name, "UserFields");
1801            assert_eq!(frag.type_condition, "User");
1802            assert_eq!(frag.selection_set.len(), 3);
1803        } else {
1804            panic!("Expected FragmentDefinition");
1805        }
1806    }
1807
1808    #[test]
1809    fn test_parse_introspection() {
1810        let query = r#"__schema { collections, fields }"#;
1811        let result = parse(query);
1812        assert!(
1813            result.is_ok(),
1814            "Failed to parse introspection: {:?}",
1815            result.err()
1816        );
1817        let doc = result.unwrap();
1818        assert_eq!(doc.operations.len(), 1);
1819
1820        if let Operation::Introspection(intro) = &doc.operations[0] {
1821            assert_eq!(intro.fields.len(), 2);
1822        } else {
1823            panic!("Expected Introspection");
1824        }
1825    }
1826
1827    #[test]
1828    fn test_parse_fragment_with_query() {
1829        let query = r#"
1830            fragment UserFields on User {
1831                id
1832                name
1833            }
1834            
1835            query GetUsers {
1836                users {
1837                    ...UserFields
1838                }
1839            }
1840        "#;
1841        let result = parse(query);
1842        assert!(
1843            result.is_ok(),
1844            "Failed to parse fragment with query: {:?}",
1845            result.err()
1846        );
1847        let doc = result.unwrap();
1848        assert_eq!(doc.operations.len(), 2);
1849    }
1850
1851    #[test]
1852    fn test_parse_aggregate_with_alias() {
1853        let query = r#"
1854            query {
1855                products {
1856                    stats: aggregate {
1857                        totalStock: sum(field: "stock")
1858                        avgPrice: avg(field: "price")
1859                        count
1860                    }
1861                }
1862            }
1863        "#;
1864        let result = parse(query);
1865        assert!(
1866            result.is_ok(),
1867            "Failed to parse aggregate: {:?}",
1868            result.err()
1869        );
1870
1871        let doc = result.unwrap();
1872        if let Operation::Query(q) = &doc.operations[0] {
1873            let products_field = &q.selection_set[0];
1874            assert_eq!(products_field.name, "products");
1875
1876            // Check inner selection set for aggregate
1877            let agg_field = &products_field.selection_set[0];
1878
1879            assert_eq!(agg_field.alias, Some("stats".to_string()));
1880            assert_eq!(agg_field.name, "aggregate");
1881
1882            // Check aggregate selection set
1883            assert_eq!(agg_field.selection_set.len(), 3, "Expected 3 agg functions");
1884
1885            // Check first agg function
1886            let total_stock = &agg_field.selection_set[0];
1887            assert_eq!(
1888                total_stock.alias,
1889                Some("totalStock".to_string()),
1890                "Expected totalStock alias"
1891            );
1892            assert_eq!(total_stock.name, "sum");
1893            assert_eq!(total_stock.arguments.len(), 1);
1894            assert_eq!(total_stock.arguments[0].name, "field");
1895
1896            // Check count
1897            let count = &agg_field.selection_set[2];
1898            assert_eq!(count.name, "count");
1899        } else {
1900            panic!("Expected Query operation");
1901        }
1902    }
1903
1904    #[test]
1905    fn test_parse_lookup_selection() {
1906        let query = r#"
1907            query {
1908                orders {
1909                    id
1910                    total
1911                    lookup(collection: "users", localField: "user_id", foreignField: "id") {
1912                        name
1913                        email
1914                    }
1915                }
1916            }
1917        "#;
1918        let result = parse(query);
1919        assert!(
1920            result.is_ok(),
1921            "Failed to parse lookup: {:?}",
1922            result.err()
1923        );
1924
1925        let doc = result.unwrap();
1926        if let Operation::Query(q) = &doc.operations[0] {
1927            let orders_field = &q.selection_set[0];
1928            assert_eq!(orders_field.name, "orders");
1929
1930            // Find the lookup field
1931            let lookup_field = orders_field
1932                .selection_set
1933                .iter()
1934                .find(|f| f.name == "lookup")
1935                .expect("Should have lookup field");
1936
1937            // Check lookup arguments were parsed
1938            assert!(
1939                lookup_field.arguments.iter().any(|a| a.name == "collection"),
1940                "Should have collection argument"
1941            );
1942            assert!(
1943                lookup_field.arguments.iter().any(|a| a.name == "localField"),
1944                "Should have localField argument"
1945            );
1946            assert!(
1947                lookup_field.arguments.iter().any(|a| a.name == "foreignField"),
1948                "Should have foreignField argument"
1949            );
1950
1951            // Check collection value
1952            let collection_arg = lookup_field
1953                .arguments
1954                .iter()
1955                .find(|a| a.name == "collection")
1956                .unwrap();
1957            if let ast::Value::String(val) = &collection_arg.value {
1958                assert_eq!(val, "users");
1959            } else {
1960                panic!("collection should be a string");
1961            }
1962
1963            // Check selection set
1964            assert_eq!(lookup_field.selection_set.len(), 2);
1965            assert_eq!(lookup_field.selection_set[0].name, "name");
1966            assert_eq!(lookup_field.selection_set[1].name, "email");
1967        } else {
1968            panic!("Expected Query operation");
1969        }
1970    }
1971
1972    #[test]
1973    fn test_parse_lookup_with_filter() {
1974        let query = r#"
1975            query {
1976                orders {
1977                    id
1978                    lookup(collection: "users", localField: "user_id", foreignField: "id", where: { active: { eq: true } }) {
1979                        name
1980                    }
1981                }
1982            }
1983        "#;
1984        let result = parse(query);
1985        assert!(
1986            result.is_ok(),
1987            "Failed to parse lookup with filter: {:?}",
1988            result.err()
1989        );
1990
1991        let doc = result.unwrap();
1992        if let Operation::Query(q) = &doc.operations[0] {
1993            let orders_field = &q.selection_set[0];
1994            let lookup_field = orders_field
1995                .selection_set
1996                .iter()
1997                .find(|f| f.name == "lookup")
1998                .expect("Should have lookup field");
1999
2000            // Check where argument exists
2001            assert!(
2002                lookup_field.arguments.iter().any(|a| a.name == "where"),
2003                "Should have where argument for filter"
2004            );
2005        } else {
2006            panic!("Expected Query operation");
2007        }
2008    }
2009}