1use std::collections::HashSet;
2
3use derive_builder::{Builder, UninitializedFieldError};
4use derive_getters::Getters;
5use query_key::{QueryKey, RawKey};
6use thiserror::Error;
7
8pub mod apply;
9mod context;
10pub mod format;
11pub mod query_arguments;
12pub mod query_key;
13
14pub use self::context::OwnedJsonPath;
15use self::query_arguments::QueryArguments;
16
17#[derive(Debug, Error)]
18pub enum Error {
19 #[error("root query builder error: {0}")]
20 RootBuilderError(#[from] RootQueryBuilderError),
21 #[error("child query builder error: {0}")]
22 ChildBuilderError(#[from] ChildQueryBuilderError),
23}
24
25#[derive(Debug, Error)]
26pub enum RootQueryValidationError {
27 #[error("root query has children with duplicated output keys: '{0}'")]
29 DuplicatedOutputKeyInRoot(RawKey),
30}
31
32#[derive(Debug, Error)]
33pub enum RootQueryBuilderError {
34 #[error("{0}")]
35 UninitializedFields(#[from] UninitializedFieldError),
36 #[error("{0}")]
37 ValidationError(#[from] RootQueryValidationError),
38}
39
40#[derive(Clone, Getters, Debug, Builder)]
41#[builder(
42 pattern = "owned",
43 build_fn(validate = "Self::validate", error = "RootQueryBuilderError")
44)]
45pub struct Query {
46 #[builder(default)]
47 pub arguments: QueryArguments,
48 #[builder(default)]
49 pub key: QueryKey,
50 #[builder(default)]
51 pub children: Vec<ChildQuery>,
52}
53
54impl QueryBuilder {
55 fn validate(&self) -> Result<(), RootQueryValidationError> {
56 self.validate_children()
57 }
58 fn validate_children(&self) -> Result<(), RootQueryValidationError> {
59 let mut output_keys = HashSet::new();
60 let Some(children) = self.children.as_ref() else {
61 return Ok(());
62 };
63 for child in children {
64 let child_query_key = child.output_key();
65 if !output_keys.insert(child_query_key) {
66 return Err(RootQueryValidationError::DuplicatedOutputKeyInRoot(
67 child_query_key.clone(),
68 ));
69 }
70 }
71 Ok(())
72 }
73}
74
75#[derive(Debug, Error)]
76pub enum ChildQueryValidationError {
77 #[error("query '{0}' has children with duplicated output keys: '{1}'")]
79 DuplicatedOutputKey(String, RawKey),
80}
81
82#[derive(Debug, Error)]
83pub enum ChildQueryBuilderError {
84 #[error("{0}")]
85 UninitializedFields(#[from] UninitializedFieldError),
86 #[error("{0}")]
87 ValidationError(#[from] ChildQueryValidationError),
88}
89
90#[derive(Clone, Getters, Debug, Builder)]
91#[builder(
92 pattern = "owned",
93 build_fn(validate = "Self::validate", error = "ChildQueryBuilderError")
94)]
95pub struct ChildQuery {
96 #[builder(default)]
97 alias: Option<RawKey>,
98 pub key: QueryKey,
100 #[builder(default)]
101 pub children: Vec<ChildQuery>,
102}
103
104impl ChildQueryBuilder {
105 fn validate(&self) -> Result<(), ChildQueryValidationError> {
106 self.validate_children()
107 }
108 fn validate_children(&self) -> Result<(), ChildQueryValidationError> {
109 let mut output_keys = HashSet::new();
110 let Some(children) = self.children.as_ref() else {
111 return Ok(());
112 };
113 for child in children {
114 let child_output_key = child.output_key();
115 if !output_keys.insert(child_output_key) {
116 let child_key = self.key.as_ref().expect("child key must be defined");
117 return Err(ChildQueryValidationError::DuplicatedOutputKey(
118 child_key.to_string(),
119 child_output_key.clone(),
120 ));
121 }
122 }
123 Ok(())
124 }
125}
126
127impl ChildQuery {
128 pub fn output_key(&self) -> &RawKey {
129 self.alias()
130 .as_ref()
131 .unwrap_or_else(|| self.key().last_key().key())
132 }
133}