Skip to content

Commit 7cff81c

Browse files
committed
refactor(WIP)!: ToSqlTokens now returns a lazy generator, instead of taking the out collection by mut reference
1 parent d31cf19 commit 7cff81c

10 files changed

Lines changed: 83 additions & 39 deletions

File tree

canyon_core/src/query/operators.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::connection::database_type::DatabaseType;
22
use crate::query::querybuilder::syntax::keyword::Keyword;
3-
use crate::query::querybuilder::syntax::tokens::{SqlTokens, Symbol, ToSqlTokens};
3+
use crate::query::querybuilder::syntax::tokens::{SqlToken, SqlTokens, Symbol, ToSqlTokens};
44
use std::fmt::Display;
55

66
/// Enumerated type for represent the comparison operations
@@ -39,7 +39,9 @@ impl Display for Comp {
3939
}
4040

4141
impl<'a> ToSqlTokens<'a> for Comp {
42-
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
42+
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
43+
let mut out = SqlTokens::with_capacity(2);
44+
4345
match *self {
4446
Comp::Eq => out.symbol(Symbol::Equals),
4547
Comp::Neq => {
@@ -58,6 +60,8 @@ impl<'a> ToSqlTokens<'a> for Comp {
5860
}
5961
Comp::Like(__kind) => out.keyword(Keyword::Like),
6062
}
63+
64+
out
6165
}
6266
}
6367

canyon_core/src/query/querybuilder/syntax/ast/select.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ pub struct SelectAst<'a> {
1212
pub joins: Vec<JoinClause<'a>>,
1313
pub order_by: Option<OrderByClause<'a>>,
1414
pub having: Option<HavingClause<'a>>,
15-
pub group_by: Vec<ColumnRef<'a>>, // TODO: ColumnRef
16-
pub limit: Option<u64>, // TODO: strong typing
15+
pub group_by: Vec<ColumnRef<'a>>,
16+
pub limit: Option<u64>, // TODO: strong typing
1717
pub offset: Option<u64>,
1818
}
1919

canyon_core/src/query/querybuilder/syntax/clause.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::query::operators::Comp;
22
use crate::query::querybuilder::syntax::column::ColumnRef;
3-
use crate::query::querybuilder::syntax::tokens::{PlaceholderKind, SqlTokens, ToSqlTokens};
3+
use crate::query::querybuilder::syntax::tokens::{
4+
PlaceholderKind, SqlToken, SqlTokens, ToSqlTokens,
5+
};
46

57
#[derive(Clone)]
68
pub struct ConditionClause<'a> {
@@ -29,12 +31,14 @@ impl ConditionClauseKind {
2931
}
3032

3133
impl<'a> ToSqlTokens<'a> for ConditionClause<'a> {
32-
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
34+
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
35+
let mut out = SqlTokens::with_capacity(4);
36+
3337
// Clause keyword
3438
out.ident(self.kind.as_str()); // NOTE: dubious
3539

3640
// Column
37-
self.column_name.to_tokens(out);
41+
out.extend(self.column_name.to_tokens());
3842

3943
// Operator
4044
out.operator(self.operator);
@@ -44,5 +48,7 @@ impl<'a> ToSqlTokens<'a> for ConditionClause<'a> {
4448
Comp::Like(kind) => PlaceholderKind::Like(kind, self.value_index),
4549
_ => PlaceholderKind::Value(self.value_index),
4650
});
51+
52+
out
4753
}
4854
}

canyon_core/src/query/querybuilder/syntax/column.rs

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use crate::query::bounds::FieldIdentifier;
2-
use crate::query::querybuilder::syntax::keyword::Keyword;
3-
use crate::query::querybuilder::syntax::symbol::Symbol::Dot;
4-
use crate::query::querybuilder::syntax::tokens::{SqlTokens, ToSqlTokens};
2+
use crate::query::querybuilder::syntax::tokens::{SqlToken, SqlTokens, ToSqlTokens};
53

64
#[derive(Debug, Clone, Default)]
75
pub struct ColumnRef<'a> {
@@ -26,18 +24,10 @@ impl<'a> From<&'a str> for ColumnRef<'a> {
2624
}
2725

2826
impl<'a> ToSqlTokens<'a> for ColumnRef<'a> {
29-
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
30-
if let Some(table_ref) = self.table {
31-
out.ident(table_ref);
32-
out.symbol(Dot)
33-
}
34-
35-
out.ident(self.column);
36-
37-
if let Some(alias) = self.alias {
38-
out.keyword(Keyword::As);
39-
out.ident(alias);
40-
}
27+
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
28+
let mut out = SqlTokens::with_capacity(__detail::calculate_column_ref_capacity(self));
29+
__impl::generate_column_ref_tokens(self, &mut out);
30+
out
4131
}
4232
}
4333

@@ -70,6 +60,9 @@ impl<'a> ColumnRef<'a> {
7060

7161
mod __impl {
7262
use crate::query::querybuilder::syntax::column::{__detail, ColumnRef};
63+
use crate::query::querybuilder::syntax::keyword::Keyword;
64+
use crate::query::querybuilder::syntax::symbol::Symbol::Dot;
65+
use crate::query::querybuilder::syntax::tokens::SqlTokens;
7366

7467
pub(crate) fn column_ref_from_str_ref(value: &str) -> ColumnRef<'_> {
7568
let trimmed = value.trim();
@@ -94,9 +87,25 @@ mod __impl {
9487
alias,
9588
}
9689
}
90+
91+
pub(crate) fn generate_column_ref_tokens<'a>(__self: &ColumnRef<'a>, out: &mut SqlTokens<'a>) {
92+
if let Some(table_ref) = __self.table {
93+
out.ident(table_ref);
94+
out.symbol(Dot)
95+
}
96+
97+
out.ident(__self.column);
98+
99+
if let Some(alias) = __self.alias {
100+
out.keyword(Keyword::As);
101+
out.ident(alias);
102+
}
103+
}
97104
}
98105

99106
mod __detail {
107+
use crate::query::querybuilder::syntax::column::ColumnRef;
108+
100109
pub(crate) fn find_case_insensitive_as(s: &str) -> Option<usize> {
101110
let bytes = s.as_bytes();
102111
for i in 0..bytes.len().saturating_sub(2) {
@@ -118,6 +127,17 @@ mod __detail {
118127
}
119128
None
120129
}
130+
131+
pub(crate) fn calculate_column_ref_capacity(__self: &ColumnRef) -> usize {
132+
let mut counter = 1; // at least the column name
133+
if __self.table.is_some() {
134+
counter += 2; // table name + dot
135+
}
136+
if __self.alias.is_some() {
137+
counter += 2; // AS + alias name
138+
}
139+
counter
140+
}
121141
}
122142

123143
#[cfg(test)]

canyon_core/src/query/querybuilder/syntax/emitter/types/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ pub(crate) fn emit_columns<'a>(columns: &Vec<ColumnRef<'a>>, tokens: &mut SqlTok
99
if i > 0 {
1010
tokens.symbol(Comma);
1111
}
12-
column.to_tokens(tokens); // TODO: change opt-out-in
12+
tokens.extend(column.to_tokens());
1313
}
1414
}

canyon_core/src/query/querybuilder/syntax/emitter/types/select.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::query::querybuilder::syntax::ast::select::SelectAst;
21
use crate::query::querybuilder::syntax::ast::BaseAst;
2+
use crate::query::querybuilder::syntax::ast::select::SelectAst;
33
use crate::query::querybuilder::syntax::emitter::{AstProcessor, SqlEmitter};
44
use crate::query::querybuilder::syntax::keyword::Keyword;
55
use crate::query::querybuilder::syntax::tokens::SqlTokens;
@@ -36,8 +36,8 @@ pub trait EmitSelect<'a>: SqlEmitter<'a> {
3636
}
3737

3838
mod __impl {
39-
use crate::query::querybuilder::syntax::ast::select::SelectAst;
4039
use crate::query::querybuilder::syntax::ast::BaseAst;
40+
use crate::query::querybuilder::syntax::ast::select::SelectAst;
4141
use crate::query::querybuilder::syntax::emitter::types::helpers;
4242
use crate::query::querybuilder::syntax::keyword::Keyword;
4343
use crate::query::querybuilder::syntax::tokens::{SqlTokens, ToSqlTokens};
@@ -48,7 +48,6 @@ mod __impl {
4848

4949
pub(crate) fn emit_from<'a>(base_ast: &BaseAst<'a>, tokens: &mut SqlTokens<'a>) {
5050
tokens.keyword(Keyword::From);
51-
base_ast.table.to_tokens(tokens);
52-
// TODO: the out opt-in params
51+
tokens.extend(base_ast.table.to_tokens());
5352
}
5453
}

canyon_core/src/query/querybuilder/syntax/join.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::query::operators::Comp;
22
use crate::query::querybuilder::syntax::column::ColumnRef;
33
use crate::query::querybuilder::syntax::keyword::Keyword;
44
use crate::query::querybuilder::syntax::table_metadata::TableMetadata;
5-
use crate::query::querybuilder::syntax::tokens::{SqlTokens, ToSqlTokens};
5+
use crate::query::querybuilder::syntax::tokens::{SqlToken, SqlTokens, ToSqlTokens};
66

77
#[derive(Debug, Clone, Copy)]
88
pub enum JoinKind {
@@ -51,13 +51,17 @@ impl<'a> JoinClause<'a> {
5151
}
5252

5353
impl<'a> ToSqlTokens<'a> for JoinClause<'a> {
54-
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
54+
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
55+
let mut out = SqlTokens::with_capacity(6);
56+
5557
out.ident(self.kind.as_str()); // NOTE: dubious
56-
self.target_table.to_tokens(out);
58+
out.extend(self.target_table.to_tokens());
5759
out.keyword(Keyword::On);
58-
self.left.to_tokens(out);
60+
out.extend(self.left.to_tokens());
5961
out.operator(self.operator);
60-
self.right.to_tokens(out);
62+
out.extend(self.right.to_tokens());
63+
64+
out
6165
}
6266
}
6367
#[test]
@@ -76,7 +80,7 @@ fn test_join_clause_basic() {
7680
};
7781

7882
let mut tokens = SqlTokens::default();
79-
join.to_tokens(&mut tokens);
83+
tokens.extend(join.to_tokens());
8084

8185
let expected = vec![
8286
SqlToken::Keyword(Keyword::Inner),

canyon_core/src/query/querybuilder/syntax/table_metadata.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::query::bounds;
22
use crate::query::querybuilder::syntax::symbol::Symbol;
3-
use crate::query::querybuilder::syntax::tokens::{SqlTokens, ToSqlTokens};
3+
use crate::query::querybuilder::syntax::tokens::{SqlToken, SqlTokens, ToSqlTokens};
44
use std::borrow::Cow;
55
use std::fmt::{Display, Formatter};
66

@@ -20,13 +20,14 @@ where
2020
}
2121

2222
impl<'a> ToSqlTokens<'a> for TableMetadata<'a> {
23-
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
24-
// TODO: this trait should disappear and just return the tokens in an iterable
23+
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
24+
let mut out = SqlTokens::with_capacity(3);
2525
if let Some(schema) = &self.schema {
2626
out.ident(schema.clone());
2727
out.symbol(Symbol::Dot);
2828
};
2929
out.ident(self.name.clone());
30+
out.into_iter()
3031
}
3132
}
3233
impl<'a> From<&'a str> for TableMetadata<'a> {

canyon_core/src/query/querybuilder/syntax/tokens.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::query::querybuilder::syntax::tokens::SqlToken::Ident;
55
use std::borrow::Cow;
66

77
pub trait ToSqlTokens<'a> {
8-
fn to_tokens(&self, out: &mut SqlTokens<'a>);
8+
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a;
99
}
1010

1111
/// 'newtype' (strong type) for the SqlToken container
@@ -36,6 +36,10 @@ impl<'a> SqlTokens<'a> {
3636
pub fn inner(self) -> Vec<SqlToken<'a>> {
3737
self.0
3838
}
39+
40+
pub fn with_capacity(capacity: usize) -> Self {
41+
Self(Vec::with_capacity(capacity))
42+
}
3943
}
4044

4145
impl<'a> IntoIterator for SqlTokens<'a> {
@@ -65,6 +69,12 @@ impl<'a> IntoIterator for &'a mut SqlTokens<'a> {
6569
}
6670
}
6771

72+
impl<'a> Extend<SqlToken<'a>> for SqlTokens<'a> {
73+
fn extend<T: IntoIterator<Item = SqlToken<'a>>>(&mut self, iter: T) {
74+
self.0.extend(iter);
75+
}
76+
}
77+
6878
#[derive(Debug, PartialEq)]
6979
pub enum SqlToken<'a> {
7080
Keyword(Keyword), // SELECT, WHERE, AND, OR, FROM, UPDATE, DELETE // TODO: model them as ctc

canyon_core/src/query/querybuilder/types/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ mod __impl {
114114
use crate::query::bounds::FieldIdentifier;
115115
use crate::query::operators::Comp;
116116
use crate::query::parameters::QueryParameter;
117+
use crate::query::querybuilder::QueryBuilder;
117118
use crate::query::querybuilder::syntax::clause::{ConditionClause, ConditionClauseKind};
118119
use crate::query::querybuilder::syntax::column::ColumnRef;
119120
use crate::query::querybuilder::syntax::emitter::AstProcessor;
120121
use crate::query::querybuilder::types::__validators;
121-
use crate::query::querybuilder::QueryBuilder;
122122
use std::error::Error;
123123

124124
pub(crate) fn generate_values_in_for_and_or_or_clause<'a, 'b, P, Z, Q>(
@@ -276,10 +276,10 @@ mod __detail {
276276

277277
mod __validators {
278278
use crate::query::parameters::QueryParameter;
279+
use crate::query::querybuilder::QueryBuilder;
279280
use crate::query::querybuilder::syntax::clause::ConditionClauseKind;
280281
use crate::query::querybuilder::syntax::emitter::AstProcessor;
281282
use crate::query::querybuilder::types::__errors;
282-
use crate::query::querybuilder::QueryBuilder;
283283
use std::error::Error;
284284
use std::fmt::Display;
285285

0 commit comments

Comments
 (0)