toql_core/
sql_builder.rs

1//! The SQL builder can build different select statements.
2pub mod build_result;
3pub mod select_stream;
4pub mod sql_builder_error;
5
6pub(crate) mod build_context;
7pub(crate) mod path_tree;
8
9use crate::{
10    error::ToqlError,
11    parameter_map::ParameterMap,
12    query::{
13        concatenation::Concatenation, field_order::FieldOrder, field_path::FieldPath,
14        query_token::QueryToken, Query,
15    },
16    result::Result,
17    role_validator::RoleValidator,
18    sql_arg::SqlArg,
19    sql_builder::{
20        build_context::BuildContext, build_result::BuildResult, sql_builder_error::SqlBuilderError,
21    },
22    sql_expr::{resolver::Resolver, SqlExpr},
23    table_mapper::{join_type::JoinType, DeserializeType, TableMapper},
24    table_mapper_registry::TableMapperRegistry,
25};
26
27use path_tree::PathTree;
28use select_stream::Select;
29use std::{
30    borrow::Cow,
31    collections::{HashMap, HashSet},
32};
33
34enum MapperOrMerge<'a> {
35    Mapper(&'a TableMapper),
36    Merge(String),
37}
38
39/// The Sql builder to build normal queries and count queries.
40pub struct SqlBuilder<'a> {
41    root_mapper: String, // root type
42    home_mapper: String, // home mapper, depends on query root
43    table_mapper_registry: &'a TableMapperRegistry,
44    roles: HashSet<String>,
45    aux_params: HashMap<String, SqlArg>, // Aux params used for all queries with this builder instance, contains typically config or auth data
46    extra_joins: HashSet<String>,        // Use this joins
47}
48
49impl<'a> SqlBuilder<'a> {
50    /// Create a new SQL Builder from a root mapper and the table mapper registry
51    pub fn new(root_mapper: &'a str, table_mapper_registry: &'a TableMapperRegistry) -> Self {
52        SqlBuilder {
53            root_mapper: root_mapper.to_string(),
54            home_mapper: root_mapper.to_string(),
55            table_mapper_registry,
56            roles: HashSet::new(),
57            aux_params: HashMap::new(),
58            extra_joins: HashSet::new(),
59        }
60    }
61    /// Use these roles with the builder.
62    pub fn with_roles(mut self, roles: HashSet<String>) -> Self {
63        self.roles = roles;
64        self
65    }
66    /// Use these auxiliary parameters with the builder.
67    pub fn with_aux_params(mut self, aux_params: HashMap<String, SqlArg>) -> Self {
68        self.aux_params = aux_params;
69        self
70    }
71    /// Add this raw SQL join statement to the result.
72    /// (For internal merge joins)
73    pub fn with_extra_join<T: Into<String>>(mut self, join: T) -> Self {
74        self.extra_joins.insert(join.into());
75        self
76    }
77
78    pub fn columns_expr(&self, query_field_path: &str, alias: &str) -> Result<(SqlExpr, SqlExpr)> {
79        let mut columns_expr = SqlExpr::new();
80        let mut join_expr = SqlExpr::new();
81
82        self.resolve_columns_expr(
83            query_field_path,
84            alias,
85            &mut columns_expr,
86            &mut join_expr,
87            //    &mut on_expr,
88        )?;
89
90        Ok((columns_expr, join_expr))
91    }
92    fn resolve_columns_expr(
93        &self,
94        query_path: &str,
95        alias: &str,
96        columns_expr: &mut SqlExpr,
97        join_expr: &mut SqlExpr,
98        //   on_expr: &mut SqlExpr,
99    ) -> Result<()> {
100        let mapper = self.mapper_for_query_path(&FieldPath::from(query_path))?;
101
102        for order in &mapper.deserialize_order {
103            match order {
104                DeserializeType::Field(name) => {
105                    let field = mapper
106                        .field(&name)
107                        .ok_or_else(|| SqlBuilderError::FieldMissing(name.to_string()))?;
108                    if !field.options.key {
109                        return Ok(());
110                    }
111                    let resolver = Resolver::new().with_self_alias(alias);
112                    if !columns_expr.is_empty() {
113                        columns_expr.push_literal(", ");
114                    }
115                    columns_expr.extend(resolver.resolve(&field.expression)?);
116                }
117                DeserializeType::Join(name) => {
118                    let join = mapper.join(&name).ok_or_else(|| {
119                        SqlBuilderError::JoinMissing(
120                            name.to_string(),
121                            mapper.table_name.to_string(),
122                        )
123                    })?;
124                    if !join.options.key {
125                        return Ok(());
126                    }
127                    let other_alias = FieldPath::from(alias).append(&mapper.canonical_table_alias);
128                    let resolver = Resolver::new()
129                        .with_self_alias(alias)
130                        .with_other_alias(&other_alias);
131
132                    join_expr.push_literal("JOIN ");
133                    join_expr.extend(resolver.resolve(&join.table_expression)?);
134                    join_expr.push_literal(" ON (");
135                    join_expr.extend(resolver.resolve(&join.on_expression)?);
136                    join_expr.push_literal(") ");
137
138                    let joined_query_path = FieldPath::from(query_path).append(&name);
139
140                    self.resolve_columns_expr(
141                        &joined_query_path,
142                        &other_alias,
143                        columns_expr,
144                        join_expr,
145                        //     on_expr,
146                    )?;
147                }
148
149                DeserializeType::Merge(_) => {}
150            }
151        }
152        Ok(())
153    }
154
155    pub fn merge_expr(&self, query_field_path: &str) -> Result<(SqlExpr, SqlExpr)> {
156        let (query_path, basename) = FieldPath::split_basename(query_field_path);
157        let mapper = self.mapper_for_query_path(&query_path)?;
158
159        // Get merge join statement and on predicate
160        let merge = mapper.merge(basename).ok_or(ToqlError::NotFound)?;
161
162        Ok((
163            merge.merge_join.to_owned(),
164            merge.merge_predicate.to_owned(),
165        ))
166    }
167
168    /// Build a delete statement from the [Query].
169    /// This build a delete filter predicate from the field filters and predicates in the query.
170    /// Any field selections are ignored.
171    ///
172    /// Returns a [BuildResult] that can be turned into SQL.
173    pub fn build_delete<M>(&mut self, query: &Query<M>) -> Result<BuildResult> {
174        let mut context = BuildContext::new();
175        let root_mapper = self
176            .table_mapper_registry
177            .mappers
178            .get(&self.home_mapper)
179            .ok_or_else(|| ToqlError::MapperMissing(self.home_mapper.to_owned()))?;
180
181        if let Some(role_expr) = &root_mapper.delete_role_expr {
182            if !RoleValidator::is_valid(&self.roles, role_expr) {
183                return Err(SqlBuilderError::RoleRequired(
184                    role_expr.to_string(),
185                    format!("mapper `{}`", self.home_mapper.to_string(),),
186                )
187                .into());
188            }
189        }
190
191        let mut result = BuildResult::new(SqlExpr::literal("DELETE"));
192
193        result.set_from(
194            root_mapper.table_name.to_owned(),
195            root_mapper.canonical_table_alias.to_owned(),
196        );
197        self.preparse_filter_joins(&query, &mut context, false)?;
198        self.build_where_clause(&query, &mut context, false, &mut result)?;
199        self.build_join_clause(&query.aux_params, &mut context, &mut result, true, false)?;
200
201        Ok(result)
202    }
203
204    //TODO move function itno separate unit
205    pub fn build_merge_delete(
206        &mut self,
207        merge_path: &FieldPath,
208        key_predicate: SqlExpr,
209    ) -> Result<SqlExpr> {
210        let root_mapper = self
211            .table_mapper_registry
212            .mappers
213            .get(&self.home_mapper)
214            .ok_or_else(|| ToqlError::MapperMissing(self.home_mapper.to_owned()))?;
215
216        let (query_path, merge_field) = FieldPath::split_basename(&merge_path);
217
218        let base_mapper = self.mapper_for_query_path(&query_path)?;
219        let root_path = FieldPath::from(&root_mapper.canonical_table_alias);
220        let canonical_path = root_path.append(&query_path);
221
222        let merge = base_mapper
223            .merge(merge_field)
224            .ok_or_else(|| SqlBuilderError::FieldMissing(merge_field.to_string()))?;
225
226        let merge_mapper = self
227            .table_mapper_registry
228            .mappers
229            .get(&merge.merged_mapper)
230            .ok_or_else(|| ToqlError::MapperMissing(merge.merged_mapper.to_string()))?;
231
232        let mut delete_expr = SqlExpr::new();
233
234        // TODO move into backend
235        // Mysql specific
236        delete_expr.push_literal("DELETE ");
237        delete_expr.push_other_alias();
238        delete_expr.push_literal(" FROM ");
239        delete_expr.push_literal(&merge_mapper.table_name);
240        delete_expr.push_literal(" ");
241        delete_expr.push_other_alias();
242        delete_expr.push_literal(" ");
243        delete_expr.extend(merge.merge_join.clone()); // Maybe conctruct custom join for postgres
244        delete_expr.push_literal(" ON ");
245        delete_expr.extend(merge.merge_predicate.clone());
246        delete_expr.push_literal(" WHERE ");
247        delete_expr.extend(key_predicate);
248
249        let canonical_merge_alias = canonical_path.append(merge_field);
250        let resolver = Resolver::new()
251            .with_self_alias(&canonical_path)
252            .with_other_alias(&canonical_merge_alias);
253
254        resolver.resolve(&delete_expr).map_err(ToqlError::from)
255    }
256
257    /// Build a normal select statement from the [Query].
258    ///
259    /// Returns a [BuildResult] that can be turned into SQL.
260    pub fn build_select<M>(
261        &mut self,
262        query_home_path: &str,
263        query: &Query<M>,
264    ) -> Result<BuildResult> {
265        let mut context = BuildContext::new();
266        context.query_home_path = query_home_path.to_string();
267
268        self.set_home_joined_mapper_for_path(&FieldPath::from(query_home_path))?;
269
270        let mapper = self
271            .table_mapper_registry
272            .get(&self.home_mapper)
273            .ok_or_else(|| ToqlError::MapperMissing(self.home_mapper.to_string()))?;
274
275        if let Some(role) = mapper.load_role_expr.as_ref() {
276            if !RoleValidator::is_valid(&self.roles, role) {
277                return Err(SqlBuilderError::RoleRequired(
278                    role.to_string(),
279                    if query_home_path.is_empty() {
280                        format!("mapper `{}`", &self.home_mapper)
281                    } else {
282                        format!("path `{}`", query_home_path)
283                    },
284                )
285                .into());
286            }
287        }
288
289        let mut result = BuildResult::new(SqlExpr::literal("SELECT"));
290        result.set_from(
291            mapper.table_name.to_owned(),
292            mapper.canonical_table_alias.to_owned(),
293        );
294
295        self.preparse_query(&query, &mut context, &mut result)?;
296        self.build_where_clause(&query, &mut context, false, &mut result)?;
297        self.build_select_clause(&query, &mut context, &mut result)?;
298        self.build_join_clause(&query.aux_params, &mut context, &mut result, false, true)?;
299        self.build_order_clause(&query.aux_params, &mut context, &mut result)?;
300
301        Ok(result)
302    }
303
304    /// Build a count statement from the [Query].
305    /// This build a count filter predicate from the field filters and predicates.
306    /// If `count_selection_ony` is true then only filters are used that are part
307    /// of the count selection ($cnt) or predicates that are marked as count_filters.
308    ///
309    /// Returns a [BuildResult] that can be turned into SQL.
310    pub fn build_count<M>(
311        &mut self,
312        query_root_path: &str,
313        query: &Query<M>,
314        count_selection_only: bool,
315    ) -> Result<BuildResult> {
316        let mut build_context = BuildContext::new();
317        build_context.query_home_path = query_root_path.to_string();
318        let root_mapper = self.root_mapper()?; // self.joined_mapper_for_path(&Self::root_field_path(root_path))?;
319
320        let mut result = BuildResult::new(SqlExpr::literal("SELECT"));
321        result.select_expr.push_literal("COUNT(*)");
322
323        result.set_from(
324            root_mapper.table_name.to_owned(),
325            root_mapper.canonical_table_alias.to_owned(),
326        );
327
328        self.build_where_clause(
329            &query,
330            &mut build_context,
331            count_selection_only,
332            &mut result,
333        )?;
334
335        self.preparse_filter_joins(&query, &mut build_context, count_selection_only)?;
336
337        self.build_join_clause(
338            &query.aux_params,
339            &mut build_context,
340            &mut result,
341            true,
342            true,
343        )?;
344
345        Ok(result)
346    }
347
348    pub fn joined_mapper_for_local_path(&self, local_path: &FieldPath) -> Result<&TableMapper> {
349        self.joined_mapper_for_path(&self.home_mapper, local_path)
350    }
351    pub fn joined_mapper_for_query_path(&self, query_path: &FieldPath) -> Result<&TableMapper> {
352        self.joined_mapper_for_path(&self.root_mapper, query_path)
353    }
354    fn joined_mapper_for_path(&self, mapper_name: &str, path: &FieldPath) -> Result<&TableMapper> {
355        let mut current_mapper = self
356            .table_mapper_registry
357            .get(mapper_name)
358            .ok_or_else(|| ToqlError::MapperMissing(mapper_name.to_string()))?;
359
360        if !path.is_empty() {
361            for p in path.children() {
362                if let Some(join) = current_mapper.joins.get(p.as_str()) {
363                    current_mapper = self
364                        .table_mapper_registry
365                        .get(&join.joined_mapper)
366                        .ok_or_else(|| ToqlError::MapperMissing(join.joined_mapper.to_string()))?;
367                } else {
368                    return Err(SqlBuilderError::JoinMissing(
369                        p.to_string(),
370                        current_mapper.table_name.to_string(),
371                    )
372                    .into());
373                }
374            }
375        }
376
377        Ok(current_mapper)
378    }
379
380    pub fn mapper_for_query_path(&self, query_path: &FieldPath) -> Result<&TableMapper> {
381        let mut current_mapper = self
382            .table_mapper_registry
383            .get(&self.root_mapper)
384            .ok_or_else(|| ToqlError::MapperMissing(self.root_mapper.to_string()))?;
385
386        if !query_path.is_empty() {
387            for p in query_path.children() {
388                if let Some(join) = current_mapper.joins.get(p.as_str()) {
389                    current_mapper = self
390                        .table_mapper_registry
391                        .get(&join.joined_mapper)
392                        .ok_or_else(|| ToqlError::MapperMissing(join.joined_mapper.to_string()))?;
393                } else if let Some(merge) = current_mapper.merges.get(p.as_str()) {
394                    current_mapper = self
395                        .table_mapper_registry
396                        .get(&merge.merged_mapper)
397                        .ok_or_else(|| ToqlError::MapperMissing(merge.merged_mapper.to_string()))?;
398                } else {
399                    return Err(ToqlError::MapperMissing(p.to_string()));
400                }
401            }
402        }
403
404        Ok(current_mapper)
405    }
406
407    fn mapper_or_merge_for_path(&'a self, local_path: &'a FieldPath) -> Result<MapperOrMerge<'a>> {
408        let mut current_mapper = self
409            .table_mapper_registry
410            .get(&self.home_mapper)
411            .ok_or_else(|| ToqlError::MapperMissing(self.home_mapper.to_string()))?;
412
413        if !local_path.is_empty() {
414            for (p, a) in local_path.children().zip(local_path.step_down()) {
415                //  dbg!(&a);
416                if current_mapper.merges.contains_key(p.as_str()) {
417                    return Ok(MapperOrMerge::Merge(a.to_string()));
418                }
419                let join = current_mapper
420                    .joins
421                    .get(p.as_str())
422                    .ok_or_else(|| ToqlError::MapperMissing(p.to_string()))?;
423                current_mapper = self
424                    .table_mapper_registry
425                    .get(&join.joined_mapper)
426                    .ok_or_else(|| ToqlError::MapperMissing(self.home_mapper.to_string()))?;
427            }
428        }
429
430        Ok(MapperOrMerge::Mapper(current_mapper))
431    }
432    fn set_home_joined_mapper_for_path(&mut self, path: &FieldPath) -> Result<()> {
433        if !path.is_empty() {
434            let mut current_type: &str = &self.root_mapper;
435            let mut current_mapper = self
436                .table_mapper_registry
437                .get(current_type)
438                .ok_or_else(|| ToqlError::MapperMissing(current_type.to_string()))?;
439
440            for p in path.children() {
441                if let Some(merge) = current_mapper.merges.get(p.as_str()) {
442                    current_mapper = self
443                        .table_mapper_registry
444                        .get(&merge.merged_mapper)
445                        .ok_or_else(|| ToqlError::MapperMissing(merge.merged_mapper.to_string()))?;
446                    current_type = &merge.merged_mapper;
447                } else if let Some(join) = current_mapper.joins.get(p.as_str()) {
448                    current_mapper = self
449                        .table_mapper_registry
450                        .get(&join.joined_mapper)
451                        .ok_or_else(|| ToqlError::MapperMissing(join.joined_mapper.to_string()))?;
452                    current_type = &join.joined_mapper;
453                } else {
454                    return Err(ToqlError::MapperMissing(p.to_string()));
455                }
456            }
457
458            self.home_mapper = current_type.to_string();
459        }
460
461        Ok(())
462    }
463
464    fn build_join_clause(
465        &self,
466        query_aux_params: &HashMap<String, SqlArg>,
467        mut build_context: &mut BuildContext,
468        result: &mut BuildResult,
469        enforce_inner_joins: bool,
470        restrict_load: bool,
471    ) -> Result<()> {
472        // Build join tree for all selected paths
473        // This allows to nest joins properly
474        // Eg [user] = [user_address, user_folder]
475        // [user_folder] = [ user_folder_owner]
476        // [user_folder_owner] =[]
477        // [user address] =[]
478
479        let mut join_tree = PathTree::new();
480
481        for local_path in &build_context.local_joined_paths {
482            join_tree.insert(&FieldPath::from(&local_path));
483        }
484
485        // Build join
486        let expr: SqlExpr = self.resolve_join(
487            &join_tree,
488            &join_tree.roots(),
489            &mut build_context,
490            enforce_inner_joins,
491            restrict_load,
492            query_aux_params,
493        )?;
494        result.join_expr.extend(expr);
495        result.join_expr.pop_literals(1); // Remove trailing whitespace
496
497        Ok(())
498    }
499    fn resolve_join(
500        &self,
501        join_tree: &PathTree,
502        nodes: &HashSet<String>,
503        build_context: &mut BuildContext,
504        enforce_inner_joins: bool,
505        restrict_load: bool,
506        query_aux_params: &HashMap<String, SqlArg>,
507    ) -> Result<SqlExpr> {
508        let mut join_expr = SqlExpr::new();
509
510        for local_path_with_join in nodes {
511            let (local_path, join_name) = FieldPath::split_basename(local_path_with_join);
512
513            let local_mapper = self.joined_mapper_for_local_path(&local_path)?;
514
515            let join = local_mapper.join(join_name).ok_or_else(|| {
516                SqlBuilderError::JoinMissing(
517                    join_name.to_string(),
518                    local_mapper.table_name.to_string(),
519                )
520            })?;
521            if restrict_load {
522                let joined_mapper = self
523                    .table_mapper_registry
524                    .get(&join.joined_mapper)
525                    .ok_or_else(|| ToqlError::MapperMissing(join.joined_mapper.to_string()))?;
526
527                if let Some(role) = joined_mapper.load_role_expr.as_ref() {
528                    if !RoleValidator::is_valid(&self.roles, role) {
529                        return Err(SqlBuilderError::RoleRequired(
530                            role.to_string(),
531                            format!(
532                                "path `{}`",
533                                FieldPath::from(&build_context.query_home_path)
534                                    .append(&local_path)
535                                    .to_string(),
536                            ),
537                        )
538                        .into());
539                    }
540                }
541            }
542
543            let canonical_self_alias = self.canonical_alias(&local_path)?.to_string();
544            let canonical_other_alias = self
545                .canonical_alias(&FieldPath::from(local_path_with_join))?
546                .to_string();
547            let resolver = Resolver::new()
548                .with_self_alias(&canonical_self_alias)
549                .with_other_alias(&canonical_other_alias);
550
551            join_expr.push_literal(if enforce_inner_joins {
552                "JOIN ("
553            } else {
554                match &join.join_type {
555                    JoinType::Inner => "JOIN (",
556                    JoinType::Left => "LEFT JOIN (",
557                }
558            });
559            let join_e = resolver.resolve(&join.table_expression)?;
560            join_expr.extend(join_e);
561            join_expr.push_literal(" ");
562
563            if let Some(subnodes) = join_tree.nodes(local_path_with_join) {
564                if !subnodes.is_empty() {
565                    let subjoin_expr = self.resolve_join(
566                        join_tree,
567                        &subnodes,
568                        build_context,
569                        enforce_inner_joins,
570                        restrict_load,
571                        query_aux_params,
572                    )?;
573                    if !subjoin_expr.is_empty() {
574                        join_expr.extend(subjoin_expr);
575                    }
576                }
577            }
578            join_expr.pop_literals(1); // Remove trailing whitespace
579            join_expr.push_literal(") ON (".to_string());
580
581            let on_expr = resolver.resolve(&join.on_expression)?;
582
583            let on_expr = {
584                let p = [
585                    &self.aux_params,
586                    &join.options.aux_params,
587                    &build_context.on_aux_params,
588                    &query_aux_params,
589                ];
590                let aux_params = ParameterMap::new(&p);
591                match &join.options.join_handler {
592                    Some(handler) => handler.build_on_predicate(on_expr, &aux_params)?,
593                    None => Resolver::resolve_aux_params(on_expr, &aux_params),
594                }
595            };
596
597            // Skip left joins with unresolved aux params
598            let on_expr = match on_expr.first_aux_param() {
599                Some(p) if join.join_type == JoinType::Left => {
600                    let query_path_with_join = FieldPath::from(&build_context.query_home_path)
601                        .append(local_path_with_join);
602                    tracing::info!("Setting condition of left join `{}` to `false`, because aux param `{}` is missing", query_path_with_join.as_str(), &p );
603                    SqlExpr::literal("false")
604                }
605                _ => on_expr,
606            };
607
608            join_expr.extend(on_expr);
609            join_expr.push_literal(") ");
610        }
611
612        Ok(join_expr)
613    }
614
615    fn build_where_clause<M>(
616        &mut self,
617        query: &Query<M>,
618        build_context: &mut BuildContext,
619        count_selection_only: bool,
620        result: &mut BuildResult,
621    ) -> Result<()> {
622        let p = [&self.aux_params, &query.aux_params];
623        let aux_params = ParameterMap::new(&p);
624
625        for token in &query.tokens {
626            match token {
627                QueryToken::Field(field) => {
628                    // Continue if field is not filtered
629                    if field.filter.is_none() {
630                        continue;
631                    }
632                    let (query_path, field_name) = FieldPath::split_basename(&field.name);
633
634                    // skip if field path is not relative to root path
635                    if !Self::home_contains(&build_context.query_home_path, &query_path) {
636                        continue;
637                    }
638
639                    if count_selection_only {
640                        let root_mapper = self.root_mapper()?;
641                        match root_mapper.selections.get("cnt") {
642                            Some(selection) => {
643                                let wildcard_path = format!("{}_*", field.name.as_str());
644                                if !selection.contains(&field.name)
645                                    && !selection.contains(&wildcard_path)
646                                {
647                                    continue;
648                                }
649                            }
650                            None => continue,
651                        }
652                    }
653
654                    // Get relative path
655                    let local_path = match query_path.localize_path(&build_context.query_home_path)
656                    {
657                        Some(l) => l,
658                        None => return Ok(()),
659                    };
660
661                    let mapper_or_merge = self.mapper_or_merge_for_path(&local_path)?;
662
663                    match mapper_or_merge {
664                        MapperOrMerge::Mapper(mapper) => {
665                            let mapped_field = mapper.fields.get(field_name).ok_or_else(|| {
666                                SqlBuilderError::FieldMissing(field.name.to_string())
667                            })?;
668
669                            if let Some(role_expr) = &mapped_field.options.load_role_expr {
670                                if !crate::role_validator::RoleValidator::is_valid(
671                                    &self.roles,
672                                    role_expr,
673                                ) {
674                                    return Err(SqlBuilderError::RoleRequired(
675                                        role_expr.to_string(),
676                                        format!(
677                                            "field `{}`",
678                                            FieldPath::from(&build_context.query_home_path)
679                                                .append(&local_path)
680                                                .append(field_name)
681                                                .to_string(),
682                                        ),
683                                    )
684                                    .into());
685                                }
686                            }
687                            let canonical_alias = self.canonical_alias(&query_path)?;
688
689                            let p = [
690                                &self.aux_params,
691                                &query.aux_params,
692                                &mapped_field.options.aux_params,
693                            ];
694                            let aux_params = ParameterMap::new(&p);
695
696                            let handler = mapped_field
697                                .options
698                                .field_handler
699                                .as_ref()
700                                .unwrap_or(&mapper.field_handler);
701                            let select_expr = handler
702                                .build_select(mapped_field.expression.clone(), &aux_params)?
703                                .unwrap_or_default();
704
705                            // Does filter apply
706                            if let Some(expr) = handler.build_filter(
707                                select_expr,
708                                field.filter.as_ref().unwrap(),
709                                &aux_params,
710                            )? {
711                                let resolver = Resolver::new().with_self_alias(&canonical_alias);
712                                let expr = resolver.resolve(&expr)?;
713                                if !result.where_expr.is_empty()
714                                    && !result.where_expr.ends_with_literal("(")
715                                {
716                                    result.where_expr.push_literal(
717                                        if field.concatenation == Concatenation::And {
718                                            " AND "
719                                        } else {
720                                            " OR "
721                                        },
722                                    );
723                                }
724                                result.where_expr.extend(expr);
725                            }
726                        }
727                        MapperOrMerge::Merge(_merge_path) => {
728                            // result.unmerged_paths.insert(merge_path);
729                        }
730                    }
731                }
732
733                QueryToken::Predicate(predicate) => {
734                    let (query_path, basename) = FieldPath::split_basename(&predicate.name);
735
736                    // skip if field path is not relative to root path
737                    if !Self::home_contains(&build_context.query_home_path, &query_path) {
738                        continue;
739                    }
740
741                    let local_path = match query_path.localize_path(&build_context.query_home_path)
742                    {
743                        Some(l) => l,
744                        None => return Ok(()),
745                    };
746
747                    let mapper_or_merge = self.mapper_or_merge_for_path(&local_path)?;
748
749                    match mapper_or_merge {
750                        MapperOrMerge::Mapper(mapper) => {
751                            let mapped_predicate =
752                                mapper.predicates.get(basename).ok_or_else(|| {
753                                    SqlBuilderError::PredicateMissing(basename.to_string())
754                                })?;
755
756                            if count_selection_only && !mapped_predicate.options.count_filter {
757                                continue;
758                            }
759
760                            if let Some(role) = &mapped_predicate.options.load_role_expr {
761                                if !RoleValidator::is_valid(&self.roles, role) {
762                                    return Err(SqlBuilderError::RoleRequired(
763                                        role.to_string(),
764                                        format!(
765                                            "predicate `@{}`",
766                                            query_path
767                                                .append(&local_path)
768                                                .append(basename)
769                                                .to_string()
770                                        ),
771                                    )
772                                    .into());
773                                }
774                            }
775
776                            let canonical_alias = self.canonical_alias(&local_path)?;
777
778                            let resolver = Resolver::new()
779                                .with_self_alias(&canonical_alias)
780                                .with_arguments(&predicate.args)
781                                .with_aux_params(&aux_params);
782
783                            let handler = mapped_predicate
784                                .options
785                                .predicate_handler
786                                .as_ref()
787                                .unwrap_or(&mapper.predicate_handler);
788
789                            if let Some(expr) = handler.build_predicate(
790                                mapped_predicate.expression.clone(),
791                                &predicate.args,
792                                &aux_params,
793                            )? {
794                                if !result.where_expr.is_empty()
795                                    && !result.where_expr.ends_with_literal("(")
796                                {
797                                    result.where_expr.push_literal(
798                                        if predicate.concatenation == Concatenation::And {
799                                            " AND "
800                                        } else {
801                                            " OR "
802                                        },
803                                    );
804                                }
805                                result.where_expr.extend(resolver.resolve(&expr)?);
806                                if !mapped_predicate.options.on_aux_params.is_empty() {
807                                    for (i, a) in &mapped_predicate.options.on_aux_params {
808                                        if let Some(v) = predicate.args.get(*i as usize) {
809                                            // tracing::info!("Setting on param `{}` = `{}`.", &a, v.to_string());
810                                            build_context
811                                                .on_aux_params
812                                                .insert(a.clone(), v.clone());
813                                        } else {
814                                            tracing::warn!("Not enough predicate arguments to set on param `{}`.", &a);
815                                        }
816                                    }
817                                }
818                            }
819                        }
820                        MapperOrMerge::Merge(_merge_path) => {}
821                    }
822                }
823                QueryToken::LeftBracket(concatenation) => {
824                    // Omit concatenation if where expression is empty or left bracket follows an outer left bracket
825                    if !result.where_expr.is_empty() && !result.where_expr.ends_with_literal("(") {
826                        result
827                            .where_expr
828                            .push_literal(if concatenation == &Concatenation::And {
829                                " AND "
830                            } else {
831                                " OR "
832                            });
833                    }
834                    result.where_expr.push_literal("(");
835                }
836                QueryToken::RightBracket => {
837                    // If parentheses are empty, remove right bracket and concatenation
838                    if result.where_expr.ends_with_literal("(") {
839                        result.where_expr.pop(); // Remove '(' token
840
841                        // Remove ' AND ' or 'OR ' token if bracket is not inner bracket
842                        // 'AND (' -> removed
843                        // 'AND ((' -> reduced to 'AND ('
844                        if result.where_expr.ends_with_literal(" AND ")
845                            || result.where_expr.ends_with_literal(" OR ")
846                        {
847                            result.where_expr.pop();
848                        }
849                    } else {
850                        result.where_expr.push_literal(")");
851                    }
852                }
853                _ => {}
854            }
855        }
856        Ok(())
857    }
858
859    fn canonical_alias<'c>(&'c self, query_path: &'c FieldPath) -> Result<Cow<String>> {
860        let root_alias = &self.root_mapper()?.canonical_table_alias;
861
862        Ok(match query_path.is_empty() {
863            false => Cow::Owned(query_path.prepend(&root_alias).to_string()),
864            true => Cow::Borrowed(&root_alias),
865        })
866    }
867
868    fn preparse_query<M>(
869        &mut self,
870        query: &Query<M>,
871        build_context: &mut BuildContext,
872        result: &mut BuildResult,
873    ) -> Result<()> {
874        result.unmerged_home_paths = self.selection_from_query(query, build_context)?;
875        build_context.update_joins_from_selections();
876
877        Ok(())
878    }
879
880    fn build_order_clause(
881        &mut self,
882        query_aux_params: &HashMap<String, SqlArg>,
883        build_context: &mut BuildContext,
884        result: &mut BuildResult,
885    ) -> Result<()> {
886        let mut ordinals = Vec::with_capacity(build_context.ordering.len());
887        for o in build_context.ordering.keys() {
888            ordinals.push(o);
889        }
890        ordinals.sort();
891
892        for n in ordinals {
893            if let Some(orderings) = build_context.ordering.get(n) {
894                for (ord, local_path_with_basename) in orderings {
895                    let (local_path, field_name) =
896                        FieldPath::split_basename(local_path_with_basename);
897                    // Skip merge fields
898                    if let Ok(mapper) = self.joined_mapper_for_local_path(&local_path) {
899                        if let Some(role) = &mapper.load_role_expr {
900                            if !RoleValidator::is_valid(&self.roles, role) {
901                                return Err(SqlBuilderError::RoleRequired(
902                                    role.to_string(),
903                                    format!(
904                                        "field `{}`",
905                                        FieldPath::from(&build_context.query_home_path)
906                                            .append(&local_path)
907                                            .to_string(),
908                                    ),
909                                )
910                                .into());
911                            }
912                        }
913
914                        let field_info = mapper
915                            .field(field_name)
916                            .ok_or_else(|| SqlBuilderError::FieldMissing(field_name.to_string()))?;
917
918                        if let Some(load_role_expr) = &field_info.options.load_role_expr {
919                            if !RoleValidator::is_valid(&self.roles, load_role_expr) {
920                                return Err(SqlBuilderError::RoleRequired(
921                                    load_role_expr.to_string(),
922                                    format!(
923                                        "field `{}`",
924                                        FieldPath::from(&build_context.query_home_path)
925                                            .append(local_path_with_basename)
926                                            .to_string(),
927                                    ),
928                                )
929                                .into());
930                            }
931                        }
932
933                        let p = [
934                            &self.aux_params,
935                            &field_info.options.aux_params,
936                            query_aux_params,
937                        ];
938                        let aux_params = ParameterMap::new(&p);
939
940                        let handler = field_info
941                            .options
942                            .field_handler
943                            .as_ref()
944                            .unwrap_or(&mapper.field_handler);
945                        let select_expr =
946                            handler.build_select(field_info.expression.clone(), &aux_params)?;
947                        let canonical_alias = self.canonical_alias(&local_path)?;
948                        if let Some(expr) = select_expr {
949                            let resolver = Resolver::new().with_self_alias(&canonical_alias);
950                            let expr = resolver.resolve(&expr)?;
951                            result.order_expr.extend(expr);
952                            result.order_expr.push_literal(match ord {
953                                FieldOrder::Asc(_) => " ASC, ",
954                                FieldOrder::Desc(_) => " DESC, ",
955                            });
956                        }
957                    }
958                }
959            }
960        }
961        if !result.order_expr.is_empty() {
962            result.order_expr.pop_literals(2); // Remove trailing ,
963        }
964
965        Ok(())
966    }
967
968    fn build_select_clause<M>(
969        &mut self,
970        query: &Query<M>,
971        build_context: &mut BuildContext,
972        result: &mut BuildResult,
973    ) -> Result<()> {
974        self.resolve_select(&FieldPath::default(), query, build_context, result)?;
975        if result.select_expr.is_empty() {
976            result.select_expr.push_literal("1");
977        } else {
978            result.select_expr.pop_literals(2); // Remove trailing ,
979        }
980        if result.select_expr.is_empty() {
981            result.select_expr.push_literal("1");
982        } else {
983            result.select_expr.pop_literals(2); // Remove trailing ,
984        }
985
986        Ok(())
987    }
988
989    fn resolve_select<M>(
990        &self,
991        local_path: &FieldPath,
992        query: &Query<M>,
993        build_context: &mut BuildContext,
994        result: &mut BuildResult,
995    ) -> Result<()> {
996        let mapper = self.joined_mapper_for_local_path(&local_path)?;
997
998        let canonical_alias = self.canonical_alias(local_path)?;
999
1000        let path_selection = build_context
1001            .local_selected_paths
1002            .contains(local_path.as_str());
1003
1004        for deserialization_type in &mapper.deserialize_order {
1005            match deserialization_type {
1006                DeserializeType::Field(field_name) => {
1007                    let local_field = if !local_path.is_empty() {
1008                        Cow::Owned(format!("{}_{}", local_path.as_str(), field_name))
1009                    } else {
1010                        Cow::Borrowed(field_name)
1011                    };
1012
1013                    let mapped_field = mapper
1014                        .field(field_name)
1015                        .ok_or_else(|| SqlBuilderError::FieldMissing(field_name.to_string()))?;
1016
1017                    let p = [
1018                        &self.aux_params,
1019                        &query.aux_params,
1020                        &mapped_field.options.aux_params,
1021                    ];
1022                    let aux_params = ParameterMap::new(&p);
1023
1024                    let role_valid = mapped_field
1025                        .options
1026                        .load_role_expr
1027                        .as_ref()
1028                        .map_or(true, |e| RoleValidator::is_valid(&self.roles, e));
1029
1030                    // If field is preselected
1031                    if mapped_field.options.preselect {
1032                        if !role_valid {
1033                            let role_string = mapped_field
1034                                .options
1035                                .load_role_expr
1036                                .as_ref()
1037                                .map_or_else(|| String::new(), |e| e.to_string());
1038                            return Err(SqlBuilderError::RoleRequired(
1039                                role_string,
1040                                format!(
1041                                    "field `{}`",
1042                                    FieldPath::from(&build_context.query_home_path)
1043                                        .append(&local_field)
1044                                        .to_string(),
1045                                ),
1046                            )
1047                            .into());
1048                        }
1049                        let handler = mapped_field
1050                            .options
1051                            .field_handler
1052                            .as_ref()
1053                            .unwrap_or(&mapper.field_handler);
1054                        let select_expr =
1055                            handler.build_select(mapped_field.expression.clone(), &aux_params)?;
1056
1057                        if let Some(expr) = select_expr {
1058                            let resolver = Resolver::new().with_self_alias(&canonical_alias);
1059                            let mut expr = resolver.resolve(&expr)?;
1060
1061                            expr.push_literal(", ");
1062
1063                            if local_path.is_empty()
1064                                || build_context
1065                                    .local_joined_paths
1066                                    .contains(local_path.as_str())
1067                            {
1068                                result.select_expr.extend(expr);
1069                                result.select_stream.push(Select::Preselect);
1070                            } else {
1071                                result.select_stream.push(Select::None);
1072                            }
1073                        } else {
1074                            // Column / expression is not selected
1075                            result.select_stream.push(Select::None);
1076                        }
1077                    }
1078                    // Field is selected through wildcard or explictit through field name
1079                    else if (path_selection && !mapped_field.options.skip_wildcard)
1080                        || build_context
1081                            .local_selected_fields
1082                            .contains(local_field.as_ref())
1083                    {
1084                        // If role is invalid raise error for explicit field and skip for wildcard selection
1085                        if !role_valid
1086                            && build_context
1087                                .local_selected_fields
1088                                .contains(local_field.as_ref())
1089                        {
1090                            let role_string = mapped_field
1091                                .options
1092                                .load_role_expr
1093                                .as_ref()
1094                                .map_or_else(|| String::new(), |e| e.to_string());
1095                            return Err(SqlBuilderError::RoleRequired(
1096                                role_string,
1097                                format!(
1098                                    "field `{}`",
1099                                    FieldPath::from(&build_context.query_home_path)
1100                                        .append(&local_field)
1101                                        .to_string()
1102                                ),
1103                            )
1104                            .into());
1105                        }
1106
1107                        if role_valid {
1108                            let handler = mapped_field
1109                                .options
1110                                .field_handler
1111                                .as_ref()
1112                                .unwrap_or(&mapper.field_handler);
1113                            let select_expr = handler
1114                                .build_select(mapped_field.expression.clone(), &aux_params)?;
1115                            if let Some(expr) = select_expr {
1116                                // Fields with unresolved aux params that are selected through a wildcard are unselected
1117                                match expr.first_aux_param() {
1118                                    Some(p) if path_selection => {
1119                                        let query_field =
1120                                            FieldPath::from(build_context.query_home_path.as_str())
1121                                                .append(local_field.as_str());
1122                                        tracing::info!("Unselecting field `{}` in struct for table `{}` because aux param `{}` is missing", query_field.as_str(), &mapper.table_name, &p );
1123                                        result.select_stream.push(Select::None);
1124                                    }
1125                                    _ => {
1126                                        let resolver =
1127                                            Resolver::new().with_self_alias(&canonical_alias);
1128                                        let expr = resolver.resolve(&expr)?;
1129                                        result.select_expr.extend(expr);
1130                                        result.select_expr.push_literal(", ");
1131                                        result.select_stream.push(Select::Query);
1132                                        result.column_counter += 1;
1133                                    }
1134                                };
1135                            } else {
1136                                result.select_stream.push(Select::None);
1137                            }
1138                        } else {
1139                            result.select_stream.push(Select::None);
1140                        }
1141                    } else {
1142                        result.select_stream.push(Select::None);
1143                    }
1144                }
1145                DeserializeType::Join(join_name) => {
1146                    let mapped_join = mapper.join(join_name).ok_or_else(|| {
1147                        SqlBuilderError::JoinMissing(
1148                            join_name.to_string(),
1149                            mapper.table_name.to_string(),
1150                        )
1151                    })?;
1152
1153                    let local_join_path = local_path.append(join_name);
1154
1155                    let role_valid = mapped_join
1156                        .options
1157                        .load_role_expr
1158                        .as_ref()
1159                        .map_or(true, |e| RoleValidator::is_valid(&self.roles, e));
1160
1161                    let role_string = if let Some(e) = &mapped_join.options.load_role_expr {
1162                        e.to_string()
1163                    } else {
1164                        String::from("")
1165                    };
1166                    // If role is invalid raise error for explicit join
1167                    if build_context
1168                        .local_joined_paths
1169                        .contains(&local_join_path.to_string())
1170                    {
1171                        if !role_valid {
1172                            return Err(SqlBuilderError::RoleRequired(
1173                                role_string,
1174                                format!(
1175                                    "path `{}`",
1176                                    FieldPath::from(&build_context.query_home_path)
1177                                        .append(&local_join_path)
1178                                        .to_string(),
1179                                ),
1180                            )
1181                            .into());
1182                        }
1183                        // Query selected join
1184                        result.select_stream.push(Select::Query);
1185
1186                        // Select fields for this path
1187                        self.resolve_select(&local_join_path, query, build_context, result)?;
1188                    } else if mapped_join.options.preselect {
1189                        if !role_valid {
1190                            return Err(SqlBuilderError::RoleRequired(
1191                                role_string,
1192                                format!(
1193                                    "path `{}`",
1194                                    FieldPath::from(&build_context.query_home_path)
1195                                        .append(&local_join_path)
1196                                        .to_string(),
1197                                ),
1198                            )
1199                            .into());
1200                        }
1201
1202                        // Add preselected join to joined paths
1203                        build_context
1204                            .local_joined_paths
1205                            .insert(local_join_path.to_string());
1206
1207                        result.select_stream.push(Select::Preselect); // Preselected join
1208
1209                        self.resolve_select(&local_join_path, query, build_context, result)?;
1210                    } else {
1211                        result.select_stream.push(Select::None); // No Join
1212                    }
1213                }
1214                DeserializeType::Merge(merge_name) => {
1215                    let mapped_merge = mapper
1216                        .merge(merge_name)
1217                        .ok_or_else(|| SqlBuilderError::MergeMissing(merge_name.to_string()))?;
1218
1219                    let query_field = FieldPath::from(build_context.query_home_path.as_str())
1220                        .append(local_path.as_str())
1221                        .append(merge_name.as_str());
1222
1223                    if mapped_merge.options.preselect
1224                        || query.contains_path_starts_with(&query_field)
1225                    {
1226                        if let Some(role_expr) = &mapped_merge.options.load_role_expr {
1227                            if !RoleValidator::is_valid(&self.roles, role_expr) {
1228                                return Err(SqlBuilderError::RoleRequired(
1229                                    role_expr.to_string(),
1230                                    format!("path `{}`", query_field.to_string(),),
1231                                )
1232                                .into());
1233                            }
1234                        }
1235
1236                        result.unmerged_home_paths.insert(query_field.to_string());
1237                    }
1238                }
1239            }
1240        }
1241
1242        Ok(())
1243    }
1244
1245    fn add_query_field(
1246        &self,
1247        query_field: &str,
1248        build_context: &mut BuildContext,
1249        unmerged_home_paths: &mut HashSet<String>,
1250        field_hidden: bool,
1251    ) -> Result<()> {
1252        let query_path = FieldPath::trim_basename(query_field);
1253        if !Self::home_contains(&build_context.query_home_path, &query_path) {
1254            return Ok(());
1255        }
1256        let local_path = match query_path.localize_path(&build_context.query_home_path) {
1257            Some(l) => l,
1258            None => return Ok(()),
1259        };
1260
1261        if let Some(local_merge_path) = self.next_merge_path(&local_path)? {
1262            unmerged_home_paths.insert(
1263                FieldPath::from(&build_context.query_home_path)
1264                    .append(&local_merge_path)
1265                    .to_string(),
1266            );
1267
1268            for path in FieldPath::from(&local_merge_path).step_up().skip(1) {
1269                build_context.local_joined_paths.insert(path.to_string());
1270            }
1271        } else {
1272            let query_field = FieldPath::from(&query_field);
1273            let local_field = match query_field.localize_path(&build_context.query_home_path) {
1274                Some(f) => f,
1275                None => return Ok(()),
1276            };
1277            if !field_hidden {
1278                build_context
1279                    .local_selected_fields
1280                    .insert(local_field.to_string());
1281            } else {
1282                // Insert path only for join (needed for hidden order, hidden filter)
1283                for path in FieldPath::from(&local_field).step_up().skip(1) {
1284                    build_context.local_joined_paths.insert(path.to_string());
1285                }
1286            }
1287        }
1288
1289        Ok(())
1290    }
1291
1292    fn resolve_custom_selection(
1293        &self,
1294        query_selection: &str,
1295        mut build_context: &mut BuildContext,
1296        mut unmerged_home_paths: &mut HashSet<String>,
1297    ) -> Result<()> {
1298        let (query_path, selection_name) = FieldPath::split_basename(query_selection);
1299        let mapper = self.mapper_for_query_path(&query_path)?;
1300        let selection = mapper
1301            .selections
1302            .get(selection_name)
1303            .ok_or_else(|| SqlBuilderError::SelectionMissing(selection_name.to_string()))?;
1304        for local_field_or_path in selection {
1305            // Path either ends with `*` or `_`
1306            if local_field_or_path.ends_with('*') || local_field_or_path.ends_with('_') {
1307                let query_path = FieldPath::from(query_path.as_str()).append(
1308                    local_field_or_path
1309                        .trim_end_matches('*')
1310                        .trim_end_matches('_'),
1311                );
1312                if let Some(local_path) = query_path.localize_path(&build_context.query_home_path) {
1313                    if let Some(merge_path) = self.next_merge_path(&local_path)? {
1314                        unmerged_home_paths.insert(
1315                            FieldPath::from(&build_context.query_home_path)
1316                                .append(&merge_path)
1317                                .to_string(),
1318                        );
1319                    } else {
1320                        build_context
1321                            .local_selected_paths
1322                            .insert(local_path.to_string());
1323                    }
1324                }
1325            } else {
1326                let query_field = FieldPath::from(query_path.as_str())
1327                    .append(local_field_or_path)
1328                    .to_string();
1329                let query_path = FieldPath::trim_basename(query_field.as_str());
1330                if let Some(local_path) = query_path.localize_path(&build_context.query_home_path) {
1331                    if let Some(merge_path) = self.next_merge_path(&local_path)? {
1332                        unmerged_home_paths.insert(
1333                            FieldPath::from(&build_context.query_home_path)
1334                                .append(&merge_path)
1335                                .to_string(),
1336                        );
1337                    } else {
1338                        self.add_query_field(
1339                            query_field.as_str(),
1340                            &mut build_context,
1341                            &mut unmerged_home_paths,
1342                            false,
1343                        )?;
1344                    }
1345                }
1346            }
1347        }
1348        Ok(())
1349    }
1350
1351    fn preparse_filter_joins<M>(
1352        &mut self,
1353        query: &Query<M>,
1354        build_context: &mut BuildContext,
1355        count_selection_only: bool,
1356    ) -> Result<()> {
1357        for token in &query.tokens {
1358            if let QueryToken::Field(field) = token {
1359                if field.filter.is_some() {
1360                    let query_path = FieldPath::from(&field.name);
1361                    if count_selection_only {
1362                        let root_mapper = self.root_mapper()?;
1363                        match root_mapper.selections.get("cnt") {
1364                            Some(selection) => {
1365                                let wildcard_path = format!("{}_*", field.name.as_str());
1366                                if !selection.contains(&field.name)
1367                                    && !selection.contains(&wildcard_path)
1368                                {
1369                                    continue;
1370                                }
1371                            }
1372                            None => continue,
1373                        }
1374                    }
1375                    if let Some(local_path_with_name) =
1376                        query_path.localize_path(&build_context.query_home_path)
1377                    {
1378                        let field_path = FieldPath::trim_basename(local_path_with_name.as_str());
1379                        if self.next_merge_path(&field_path)?.is_none() {
1380                            for path in field_path.step_up() {
1381                                build_context.local_joined_paths.insert(path.to_string());
1382                            }
1383                        }
1384                    }
1385                }
1386            }
1387        }
1388        Ok(())
1389    }
1390    fn selection_from_query<M>(
1391        &mut self,
1392        query: &Query<M>,
1393        mut build_context: &mut BuildContext,
1394    ) -> Result<HashSet<String>> {
1395        let mut unmerged_home_paths = HashSet::new();
1396
1397        for token in &query.tokens {
1398            match token {
1399                QueryToken::Field(field) => {
1400                    self.add_query_field(
1401                        &field.name,
1402                        &mut build_context,
1403                        &mut unmerged_home_paths,
1404                        field.hidden,
1405                    )?;
1406                    if let Some(o) = &field.order {
1407                        let order = match o {
1408                            FieldOrder::Asc(o) => o,
1409                            FieldOrder::Desc(o) => o,
1410                        };
1411                        let query_path = FieldPath::from(&field.name);
1412                        if let Some(local_path_with_name) =
1413                            query_path.localize_path(&build_context.query_home_path)
1414                        {
1415                            build_context
1416                                .ordering
1417                                .entry(*order)
1418                                .or_insert_with(Vec::new)
1419                                .push((o.to_owned(), local_path_with_name.to_string()));
1420                        }
1421                    }
1422                }
1423                QueryToken::Wildcard(wildcard) => {
1424                    // TODO: Wildcard path may have ending _, check why and to remove
1425                    let query_path = FieldPath::from(&wildcard.path.trim_end_matches('_'));
1426
1427                    if let Some(local_path) =
1428                        query_path.localize_path(&build_context.query_home_path)
1429                    {
1430                        // if !local_path.is_empty() {
1431                        // local_selected_paths.insert(local_path.to_string());
1432                        if let Some(local_merge_path) = self.next_merge_path(&local_path)? {
1433                            // insert full query path
1434                            unmerged_home_paths.insert(
1435                                FieldPath::from(&build_context.query_home_path)
1436                                    .append(&local_merge_path)
1437                                    .to_string(),
1438                            );
1439                            for path in FieldPath::from(&local_merge_path).step_up().skip(1) {
1440                                build_context.local_joined_paths.insert(path.to_string());
1441                            }
1442                        } else {
1443                            build_context
1444                                .local_selected_paths
1445                                .insert(local_path.to_string());
1446                        }
1447                        // }
1448                    }
1449
1450                    //  relative_paths.insert(wildcard.path.to_string());
1451                }
1452                QueryToken::Selection(selection) => {
1453                    let (query_path, selection_name) = FieldPath::split_basename(&selection.name);
1454
1455                    // Process only if selection path is a valid local path
1456                    if let Some(local_path) =
1457                        query_path.localize_path(&build_context.query_home_path)
1458                    {
1459                        if let Some(local_merge_path) = self.next_merge_path(&local_path)? {
1460                            // insert full query path
1461                            unmerged_home_paths.insert(
1462                                FieldPath::from(&build_context.query_home_path)
1463                                    .append(&local_merge_path)
1464                                    .to_string(),
1465                            );
1466                            for path in FieldPath::from(&local_merge_path).step_up().skip(1) {
1467                                build_context.local_joined_paths.insert(path.to_string());
1468                            }
1469                        } else {
1470                            let mapper = self.joined_mapper_for_local_path(&local_path)?;
1471                            match selection_name {
1472                                "all" => {
1473                                    // Add all fields explicitly. This will include fields that are skip_wildcard
1474                                    for deserialization_type in &mapper.deserialize_order {
1475                                        if let DeserializeType::Field(field_name) =
1476                                            deserialization_type
1477                                        {
1478                                            // Skip invliad load role restriction
1479                                            let f =
1480                                                mapper.fields.get(field_name).ok_or_else(|| {
1481                                                    SqlBuilderError::FieldMissing(
1482                                                        field_name.to_string(),
1483                                                    )
1484                                                })?;
1485                                            if let Some(role_expr) = &f.options.load_role_expr {
1486                                                if !RoleValidator::is_valid(&self.roles, role_expr)
1487                                                {
1488                                                    continue;
1489                                                }
1490                                            }
1491
1492                                            let query_field = FieldPath::from(
1493                                                build_context.query_home_path.as_str(),
1494                                            )
1495                                            .append(local_path.as_str())
1496                                            .append(field_name)
1497                                            .to_string();
1498                                            self.add_query_field(
1499                                                query_field.as_str(),
1500                                                &mut build_context,
1501                                                &mut unmerged_home_paths,
1502                                                false,
1503                                            )?;
1504                                        }
1505                                    }
1506                                }
1507                                "mut" => {
1508                                    // Add all mutable fields on that path
1509                                    // (additionally keys and preselects will be added when building actual select expression)
1510                                    for deserialization_type in &mapper.deserialize_order {
1511                                        if let DeserializeType::Field(field_name) =
1512                                            deserialization_type
1513                                        {
1514                                            let f =
1515                                                mapper.fields.get(field_name).ok_or_else(|| {
1516                                                    SqlBuilderError::FieldMissing(
1517                                                        field_name.to_string(),
1518                                                    )
1519                                                })?;
1520                                            // Skip invalid load role restriction
1521                                            if let Some(role_expr) = &f.options.load_role_expr {
1522                                                if !RoleValidator::is_valid(&self.roles, role_expr)
1523                                                {
1524                                                    continue;
1525                                                }
1526                                            }
1527                                            // Skip invalid mut role restriction
1528                                            if let Some(role_expr) = &f.options.update_role_expr {
1529                                                if !RoleValidator::is_valid(&self.roles, role_expr)
1530                                                {
1531                                                    continue;
1532                                                }
1533                                            }
1534                                            if !f.options.skip_mut && !f.options.key {
1535                                                let query_field = FieldPath::from(
1536                                                    build_context.query_home_path.as_str(),
1537                                                )
1538                                                .append(local_path.as_str())
1539                                                .append(field_name)
1540                                                .to_string();
1541                                                self.add_query_field(
1542                                                    query_field.as_str(),
1543                                                    &mut build_context,
1544                                                    &mut unmerged_home_paths,
1545                                                    false,
1546                                                )?;
1547                                            }
1548                                        }
1549                                    }
1550                                }
1551                                "cnt" => {
1552                                    let selection = mapper.selections.get("cnt");
1553                                    if let Some(selection) = selection {
1554                                        // Select fields that are used for counting
1555                                        // Additionally to keys and preselects
1556                                        for deserialization_type in &mapper.deserialize_order {
1557                                            if let DeserializeType::Field(query_field_name) =
1558                                                deserialization_type
1559                                            {
1560                                                let wildcard_path =
1561                                                    format!("{}_*", query_field_name);
1562                                                if !selection.contains(&query_field_name)
1563                                                    && !selection.contains(&wildcard_path)
1564                                                {
1565                                                    continue;
1566                                                }
1567
1568                                                self.add_query_field(
1569                                                    &query_field_name,
1570                                                    &mut build_context,
1571                                                    &mut unmerged_home_paths,
1572                                                    false,
1573                                                )?;
1574                                            }
1575                                        }
1576                                    } else {
1577                                        // If cnt selection is undefined, select keys and preselects
1578                                        for deserialization_type in &mapper.deserialize_order {
1579                                            if let DeserializeType::Field(field_name) =
1580                                                deserialization_type
1581                                            {
1582                                                let f = mapper.fields.get(field_name).ok_or_else(
1583                                                    || {
1584                                                        SqlBuilderError::FieldMissing(
1585                                                            field_name.to_string(),
1586                                                        )
1587                                                    },
1588                                                )?;
1589                                                if f.options.key || f.options.preselect {
1590                                                    let query_field = FieldPath::from(
1591                                                        build_context.query_home_path.as_str(),
1592                                                    )
1593                                                    .append(local_path.as_str())
1594                                                    .append(field_name)
1595                                                    .to_string();
1596                                                    self.add_query_field(
1597                                                        query_field.as_str(),
1598                                                        &mut build_context,
1599                                                        &mut unmerged_home_paths,
1600                                                        false,
1601                                                    )?;
1602                                                }
1603                                            }
1604                                        }
1605                                    }
1606                                }
1607                                _ => {
1608                                    self.resolve_custom_selection(
1609                                        &selection.name,
1610                                        &mut build_context,
1611                                        &mut unmerged_home_paths,
1612                                    )?;
1613                                }
1614                            }
1615                        }
1616                    } else {
1617                        // Evaluate selections that are not local to the selection path.
1618                        // Custom and standart selections may start above the current home path
1619                        // Eg. Selection `*, users_name` on top path must also be evaluated in home path `users`,
1620                        // because `users_name` affects selection.
1621                        if build_context
1622                            .query_home_path
1623                            .starts_with(query_path.as_str())
1624                        {
1625                            if selection_name != "cnt"
1626                                && selection_name != "mut"
1627                                && selection_name != "all"
1628                            {
1629                                self.resolve_custom_selection(
1630                                    &selection.name,
1631                                    &mut build_context,
1632                                    &mut unmerged_home_paths,
1633                                )?;
1634                            }
1635                        }
1636                    }
1637                }
1638                QueryToken::Predicate(predicate) => {
1639                    let query_path = FieldPath::trim_basename(&predicate.name);
1640                    if let Some(local_path) =
1641                        query_path.localize_path(&build_context.query_home_path)
1642                    {
1643                        // Skip local path if it contains a merged field
1644                        if self.joined_mapper_for_query_path(&local_path).is_ok() {
1645                            for partial_local_path in FieldPath::from(&local_path).step_up() {
1646                                // Skip predicate name
1647                                build_context
1648                                    .local_joined_paths
1649                                    .insert(partial_local_path.to_string());
1650                            }
1651                        }
1652                    }
1653                }
1654                _ => {}
1655            }
1656        }
1657
1658        Ok(unmerged_home_paths)
1659    }
1660
1661    fn root_mapper(&self) -> Result<&TableMapper> {
1662        self.table_mapper_registry
1663            .get(&self.home_mapper)
1664            .ok_or_else(|| ToqlError::MapperMissing(self.home_mapper.to_string()))
1665    }
1666    fn next_merge_path(&self, local_path: &FieldPath) -> Result<Option<String>> {
1667        let mut current_mapper = self
1668            .table_mapper_registry
1669            .get(&self.home_mapper)
1670            .ok_or_else(|| ToqlError::MapperMissing(self.home_mapper.to_string()))?;
1671
1672        for (mapper_name, merge_path) in local_path.children().zip(local_path.step_down()) {
1673            if current_mapper.merged_mapper(mapper_name.as_str()).is_some() {
1674                return Ok(Some(merge_path.to_string()));
1675            } else if let Some(joined_mapper_name) =
1676                current_mapper.joined_mapper(mapper_name.as_str())
1677            {
1678                let m = self
1679                    .table_mapper_registry
1680                    .get(&joined_mapper_name)
1681                    .ok_or_else(|| ToqlError::MapperMissing(mapper_name.to_string()))?;
1682                current_mapper = m;
1683            } else {
1684                break;
1685            }
1686        }
1687        Ok(None)
1688    }
1689
1690    fn home_contains(home_path: &str, query_path: &FieldPath) -> bool {
1691        let r = match (home_path.is_empty(), query_path.is_empty()) {
1692            (true, true) => true,
1693            (false, true) => false,
1694            (true, false) => true,
1695            (false, false) => query_path.as_str().starts_with(home_path),
1696        };
1697
1698        r
1699    }
1700}