drasi_query_ast/
api.rs

1// Copyright 2024 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashSet;
16use thiserror::Error;
17
18use crate::ast;
19
20const ERR_PARSE: &str = "parser error";
21const ERR_MISSING_GROUP_BY: &str = "Non-grouped RETURN expressions must appear in GROUP BY clause";
22const ERR_UNALIASED_COMPLEX: &str = "Complex expression must have an alias";
23const ERR_ID_NOT_IN_SCOPE: &str = "Identifier not found in current scope";
24
25pub trait QueryParser: Send + Sync {
26    fn parse(&self, input: &str) -> Result<ast::Query, QueryParseError>;
27}
28
29pub trait QueryConfiguration: Send + Sync {
30    fn get_aggregating_function_names(&self) -> HashSet<String>;
31}
32
33#[derive(Error, Debug)]
34pub enum QueryParseError {
35    #[error("{ERR_PARSE}: {0}")]
36    ParserError(Box<dyn std::error::Error + Send + Sync>),
37
38    #[error("{ERR_MISSING_GROUP_BY}")]
39    MissingGroupByKey,
40
41    #[error("{ERR_UNALIASED_COMPLEX}: {0}")]
42    UnaliasedComplexExpression(String),
43
44    #[error("{ERR_ID_NOT_IN_SCOPE}: {0}")]
45    IdentifierNotInScope(String),
46}
47
48// This is used to map the error to a static string for the PEG parser.
49// The PEG parser requires &'static str, so we must define const strings. This is a PEG limitation.
50// TODO: Should improve this later to provide a more detailed error message.
51impl QueryParseError {
52    pub fn as_peg_error(&self) -> &'static str {
53        match self {
54            QueryParseError::ParserError(_) => ERR_PARSE,
55            QueryParseError::MissingGroupByKey => ERR_MISSING_GROUP_BY,
56            QueryParseError::UnaliasedComplexExpression(_) => ERR_UNALIASED_COMPLEX,
57            QueryParseError::IdentifierNotInScope(_) => ERR_ID_NOT_IN_SCOPE,
58        }
59    }
60}