1pub mod builder;
3pub mod executor;
4pub mod interface;
5pub mod optimizer;
6pub mod parallel_parser;
7pub mod parser;
8pub mod planner;
9pub mod view;
10
11pub use builder::{Execute, Query, QueryOne, QueryOptional, QueryScalar, ScalarValue};
12pub use executor::{
13 FilterOperator, HashAggregateOperator, HashJoinOperator, LimitOperator, PhysicalOperator,
14 ProjectionOperator, SortOperator, TableScanOperator, evaluate_expr,
15};
16pub use optimizer::{OptimizationRule, QueryOptimizer};
17pub use parallel_parser::ParallelSqlParser;
18pub use parser::SqlParser;
19pub use planner::{
20 AggregateExpr, AggregateFunction, BinaryOperator, Expr, JoinType, LogicalPlan, LogicalPlanner,
21 PhysicalAggExpr, PhysicalExpr, PhysicalPlan, PhysicalPlanner, SortExpr,
22};
23pub trait StringCaseExt {
24 fn starts_with_ignore_ascii_case(&self, prefix: &str) -> bool;
25 fn contains_ignore_ascii_case(&self, substring: &str) -> bool;
26}
27
28impl StringCaseExt for str {
29 fn starts_with_ignore_ascii_case(&self, prefix: &str) -> bool {
30 if self.len() < prefix.len() {
31 false
32 } else {
33 self.is_char_boundary(prefix.len()) && self[..prefix.len()].eq_ignore_ascii_case(prefix)
34 }
35 }
36
37 fn contains_ignore_ascii_case(&self, substring: &str) -> bool {
38 if substring.is_empty() {
39 return true;
40 }
41 if self.len() < substring.len() {
42 return false;
43 }
44
45 for (idx, _) in self.char_indices() {
47 if idx + substring.len() <= self.len() {
48 if self.is_char_boundary(idx + substring.len())
49 && self[idx..idx + substring.len()].eq_ignore_ascii_case(substring)
50 {
51 return true;
52 }
53 } else {
54 break;
55 }
56 }
57 false
58 }
59}