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