Skip to content

Commit 3a9307b

Browse files
committed
refactor(WIP)!: given the emitters real entity like behaviour
1 parent a1b67b8 commit 3a9307b

26 files changed

Lines changed: 531 additions & 388 deletions

canyon_core/src/query/operators.rs

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

56
/// Enumerated type for represent the comparison operations
67
/// in SQL sentences
@@ -38,24 +39,24 @@ impl Display for Comp {
3839
}
3940

4041
impl<'a> ToSqlTokens<'a> for Comp {
41-
fn to_tokens(&self, out: &mut Vec<SqlToken<'a>>) {
42+
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
4243
match *self {
43-
Comp::Eq => out.push(SqlToken::Symbol(Symbol::Equals)),
44+
Comp::Eq => out.symbol(Symbol::Equals),
4445
Comp::Neq => {
45-
out.push(SqlToken::Symbol(Symbol::Not));
46-
out.push(SqlToken::Symbol(Symbol::Equals))
46+
out.symbol(Symbol::Not);
47+
out.symbol(Symbol::Equals)
4748
}
48-
Comp::Gt => out.push(SqlToken::Symbol(Symbol::RAngle)),
49+
Comp::Gt => out.symbol(Symbol::RAngle),
4950
Comp::GtEq => {
50-
out.push(SqlToken::Symbol(Symbol::RAngle));
51-
out.push(SqlToken::Symbol(Symbol::Equals))
51+
out.symbol(Symbol::RAngle);
52+
out.symbol(Symbol::Equals)
5253
}
53-
Comp::Lt => out.push(SqlToken::Symbol(Symbol::LAngle)),
54+
Comp::Lt => out.symbol(Symbol::LAngle),
5455
Comp::LtEq => {
55-
out.push(SqlToken::Symbol(Symbol::LAngle));
56-
out.push(SqlToken::Symbol(Symbol::Equals))
56+
out.symbol(Symbol::LAngle);
57+
out.symbol(Symbol::Equals)
5758
}
58-
Comp::Like(__kind) => out.push(SqlToken::new_keyword("LIKE"))
59+
Comp::Like(__kind) => out.keyword(Keyword::Like)
5960
}
6061
}
6162
}
Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
1-
use crate::query::querybuilder::syntax::emitter::{
2-
AsEmitBody, AsEmitFrom, AsEmitKind, AstProcessor, EmitBody, EmitFrom, EmitKind, ToSql,
3-
};
4-
use crate::query::querybuilder::syntax::table_metadata::TableMetadata;
5-
use crate::query::querybuilder::syntax::tokens::{SqlToken, ToSqlTokens};
1+
use crate::query::querybuilder::syntax::emitter::AstProcessor;
2+
use crate::query::querybuilder::syntax::query_kind::QueryKind;
63

74
pub struct DeleteAst {}
85

9-
impl AstProcessor for DeleteAst {}
10-
impl<'a> ToSql<'a> for DeleteAst {}
11-
12-
impl<'a> EmitKind<'a> for DeleteAst {
13-
fn emit_kind(&self, out: &mut Vec<SqlToken<'a>>) {
14-
out.push(SqlToken::new_keyword("DELETE"));
15-
}
16-
}
17-
impl<'a> EmitFrom<'a> for DeleteAst {
18-
fn emit_from<'b>(&self, meta: &TableMetadata<'b>, out: &mut Vec<SqlToken<'b>>) {
19-
out.push(SqlToken::new_keyword("FROM"));
20-
meta.to_tokens(out);
6+
impl AstProcessor for DeleteAst {
7+
fn query_kind(&self) -> QueryKind {
8+
QueryKind::Delete
219
}
2210
}
2311

@@ -33,18 +21,3 @@ impl DeleteAst {
3321
}
3422
}
3523

36-
impl<'a> AsEmitKind<'a> for DeleteAst {
37-
fn as_emit_kind(&self) -> Option<&dyn EmitKind<'a>> {
38-
Some(self as &dyn EmitKind<'a>)
39-
}
40-
}
41-
impl<'a> AsEmitFrom<'a> for DeleteAst {
42-
fn as_emit_from(&self) -> Option<&dyn EmitFrom<'a>> {
43-
Some(self as &dyn EmitFrom<'a>)
44-
}
45-
}
46-
impl<'a> AsEmitBody<'a> for DeleteAst {
47-
fn as_emit_body(&self) -> Option<&dyn EmitBody<'a>> {
48-
None
49-
}
50-
}

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

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,16 @@
11
use crate::query::parameters::QueryParameter;
2-
use crate::query::querybuilder::syntax::emitter::{EmitBody, EmitFrom, EmitKind};
3-
use crate::query::querybuilder::syntax::table_metadata::TableMetadata;
4-
use crate::query::querybuilder::syntax::tokens::Symbol::{LParen, RParen};
5-
use crate::query::querybuilder::syntax::tokens::{SqlToken, Symbol, ToSqlTokens};
6-
use std::borrow::Cow;
2+
use crate::query::querybuilder::syntax::column::ColumnRef;
3+
use crate::query::querybuilder::syntax::emitter::AstProcessor;
4+
use crate::query::querybuilder::syntax::query_kind::QueryKind;
75

6+
#[derive(Default)]
87
pub struct InsertAst<'a> {
9-
pub columns: Vec<&'a str>,
8+
pub columns: Vec<ColumnRef<'a>>,
109
pub values: Vec<&'a dyn QueryParameter>,
1110
}
1211

13-
impl<'a> EmitKind<'a> for InsertAst<'a> {
14-
fn emit_kind(&self, out: &mut Vec<SqlToken<'a>>) {
15-
out.push(SqlToken::new_keyword("INSERT"));
16-
}
17-
}
18-
impl<'a> EmitFrom<'a> for InsertAst<'a> {
19-
fn emit_from<'b>(&self, meta: &TableMetadata<'b>, out: &mut Vec<SqlToken<'b>>) {
20-
if !self.columns.is_empty() {
21-
// this can't be emitted here
22-
// TODO: can we create like a pre-validator trait a-la-emit-kind but for checking invariants?
23-
out.push(SqlToken::new_ident("INTO"));
24-
meta.to_tokens(out);
25-
out.push(SqlToken::Symbol(LParen));
26-
for (i, c) in self.columns.iter().enumerate() {
27-
if i > 0 {
28-
out.push(SqlToken::Symbol(Symbol::Comma));
29-
}
30-
//out.push(SqlToken::new_ident(c));
31-
}
32-
out.push(SqlToken::Symbol(Symbol::RParen));
33-
}
34-
}
35-
}
36-
impl<'a> EmitBody<'a> for InsertAst<'a> {
37-
fn emit_body(&self, out: &mut Vec<SqlToken<'a>>) {
38-
out.push(SqlToken::Keyword(Cow::Borrowed("VALUES")));
39-
out.push(SqlToken::Symbol(LParen));
40-
// for i in 0..self.values_count {
41-
// if i > 0 { out.push(SqlToken::Symbol(Comma)); }
42-
// // out.push(SqlToken::PlaceholderNext); self as the real type and call a custom impl
43-
// }
44-
out.push(SqlToken::Symbol(RParen));
45-
}
12+
impl<'a> AstProcessor for InsertAst<'a> {
13+
fn query_kind(&self) -> QueryKind { QueryKind::Insert }
4614
}
4715

4816
impl<'a> InsertAst<'a> {
Lines changed: 5 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
use crate::query::querybuilder::syntax::column::ColumnRef;
2-
use crate::query::querybuilder::syntax::emitter::{
3-
AsEmitBody, AsEmitFrom, AsEmitKind, AstProcessor, EmitBody, EmitFrom, EmitKind, ToSql,
4-
};
2+
use crate::query::querybuilder::syntax::emitter::AstProcessor;
53
use crate::query::querybuilder::syntax::having::HavingClause;
64
use crate::query::querybuilder::syntax::join::JoinClause;
75
use crate::query::querybuilder::syntax::order::OrderByClause;
8-
use crate::query::querybuilder::syntax::symbol::Symbol;
9-
use crate::query::querybuilder::syntax::table_metadata::TableMetadata;
10-
use crate::query::querybuilder::syntax::tokens::{SqlToken, ToSqlTokens};
11-
use std::borrow::Cow;
6+
use crate::query::querybuilder::syntax::query_kind::QueryKind;
127

138
#[derive(Default)]
149
pub struct SelectAst<'a> {
@@ -35,61 +30,8 @@ impl<'a> SelectAst<'a> {
3530
}
3631
}
3732

38-
impl<'a> ToSql<'a> for SelectAst<'a> {}
39-
40-
impl<'a> AstProcessor for SelectAst<'a> {}
41-
42-
impl<'a> EmitKind<'a> for SelectAst<'a> {
43-
fn emit_kind(&self, out: &mut Vec<SqlToken<'a>>) {
44-
out.push(SqlToken::Keyword(Cow::Borrowed("SELECT")));
45-
}
46-
}
47-
48-
impl<'a> EmitFrom<'a> for SelectAst<'a> {
49-
fn emit_from(&self, meta: &TableMetadata<'a>, out: &mut Vec<SqlToken<'a>>) {
50-
// columns
51-
if self.columns.is_empty() {
52-
out.push(SqlToken::Symbol(Symbol::Asterisk));
53-
} else {
54-
for (i, col) in self.columns.iter().enumerate() {
55-
if i > 0 {
56-
out.push(SqlToken::Symbol(Symbol::Comma));
57-
}
58-
col.to_tokens(out);
59-
}
60-
}
61-
// FROM
62-
out.push(SqlToken::new_keyword("FROM"));
63-
meta.to_tokens(out);
64-
}
65-
}
66-
impl<'a> EmitBody<'a> for SelectAst<'a> {
67-
fn emit_body(&self, out: &mut Vec<SqlToken<'a>>) {
68-
for j in &self.joins {
69-
j.to_tokens(out)
70-
}
71-
for c in &self._inner.conditions {
72-
c.accept(self);
73-
}
74-
}
75-
}
76-
77-
// tell the system that SelectAst supports these phases:
78-
impl<'a> AsEmitKind<'a> for SelectAst<'a> {
79-
fn as_emit_kind(&self) -> Option<&dyn EmitKind<'a>> {
80-
Some(self as &dyn EmitKind<'a>)
81-
}
82-
}
83-
impl<'a> AsEmitFrom<'a> for SelectAst<'a> {
84-
fn as_emit_from(&self) -> Option<&dyn EmitFrom<'a>> {
85-
Some(self as &dyn EmitFrom<'a>)
86-
}
87-
}
88-
impl<'a> AsEmitBody<'a> for SelectAst<'a> {
89-
fn as_emit_body(&self) -> Option<&dyn EmitBody<'a>> {
90-
Some(self as &dyn EmitBody<'a>)
33+
impl<'a> AstProcessor for SelectAst<'a> {
34+
fn query_kind(&self) -> QueryKind {
35+
QueryKind::Select
9136
}
9237
}
93-
// impl<'a> AsEmitConditions<'a> for SelectAst<'a> {
94-
// fn as_emit_conditions(&self) -> Option<&dyn EmitConditions<'a>> { Some(self as &dyn EmitConditions<'a>) }
95-
// }
Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,15 @@
11
use crate::query::querybuilder::syntax::column::ColumnRef;
2-
use crate::query::querybuilder::syntax::emitter::{
3-
AsEmitBody, AsEmitFrom, AsEmitKind, AstProcessor, EmitBody, EmitFrom, EmitKind, ToSql,
4-
};
5-
use crate::query::querybuilder::syntax::tokens::SqlToken;
2+
use crate::query::querybuilder::syntax::emitter::AstProcessor;
3+
use crate::query::querybuilder::syntax::query_kind::QueryKind;
64

75
pub struct UpdateAst<'a> {
86
pub columns: Vec<ColumnRef<'a>>,
97
}
108

11-
impl<'a> AstProcessor for UpdateAst<'a> {}
12-
impl<'a> ToSql<'a> for UpdateAst<'a> {}
13-
14-
impl<'a> EmitKind<'a> for UpdateAst<'a> {
15-
fn emit_kind(&self, out: &mut Vec<SqlToken<'a>>) {
16-
out.push(SqlToken::new_keyword("UPDATE"));
17-
}
9+
impl<'a> AstProcessor for UpdateAst<'a> {
10+
fn query_kind(&self) -> QueryKind { QueryKind::Update }
1811
}
1912

20-
impl<'a> EmitBody<'a> for UpdateAst<'a> {
21-
fn emit_body(&self, out: &mut Vec<SqlToken<'a>>) {
22-
out.push(SqlToken::new_keyword("SET"));
23-
24-
// for (i, (col, _val)) in self.columns.iter().enumerate() {
25-
// if i > 0 { out.push(SqlToken::Symbol(",")); }
26-
// out.push(SqlToken::Ident(col));
27-
// out.push(SqlToken::Symbol("="));
28-
// out.push(SqlToken::PlaceholderNext);
29-
// }
30-
}
31-
}
3213

3314
impl<'a> Default for UpdateAst<'a> {
3415
fn default() -> Self {
@@ -43,19 +24,3 @@ impl<'a> UpdateAst<'a> {
4324
}
4425
}
4526
}
46-
47-
impl<'a> AsEmitKind<'a> for UpdateAst<'a> {
48-
fn as_emit_kind(&self) -> Option<&dyn EmitKind<'a>> {
49-
Some(self as &dyn EmitKind<'a>)
50-
}
51-
}
52-
impl<'a> AsEmitFrom<'a> for UpdateAst<'a> {
53-
fn as_emit_from(&self) -> Option<&dyn EmitFrom<'a>> {
54-
None
55-
}
56-
}
57-
impl<'a> AsEmitBody<'a> for UpdateAst<'a> {
58-
fn as_emit_body(&self) -> Option<&dyn EmitBody<'a>> {
59-
Some(self as &dyn EmitBody<'a>)
60-
}
61-
}

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

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

65
#[derive(Clone)]
76
pub struct ConditionClause<'a> {
@@ -30,21 +29,21 @@ impl ConditionClauseKind {
3029
}
3130

3231
impl<'a> ToSqlTokens<'a> for ConditionClause<'a> {
33-
fn to_tokens(&self, out: &mut Vec<SqlToken<'a>>) {
32+
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
3433

3534
// Clause keyword
36-
out.push(SqlToken::new_keyword(self.kind.as_str()));
35+
out.ident(self.kind.as_str()); // NOTE: dubious
3736

3837
// Column
3938
self.column_name.to_tokens(out);
4039

4140
// Operator
42-
out.push(Operator(self.operator));
41+
out.operator(self.operator);
4342

4443
// Value placeholder
45-
out.push(Placeholder(match self.operator {
44+
out.placeholder(match self.operator {
4645
Comp::Like(kind) => PlaceholderKind::Like(kind, self.value_index),
4746
_ => PlaceholderKind::Value(self.value_index)
48-
}));
47+
});
4948
}
5049
}

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
use std::borrow::Cow;
12
use crate::query::bounds::FieldIdentifier;
3+
use crate::query::querybuilder::syntax::keyword::Keyword;
24
use crate::query::querybuilder::syntax::symbol::Symbol::Dot;
3-
use crate::query::querybuilder::syntax::tokens::{SqlToken, ToSqlTokens};
5+
use crate::query::querybuilder::syntax::tokens::{SqlToken, SqlTokens, ToSqlTokens};
46

57
#[derive(Debug, Clone, Default)]
68
pub struct ColumnRef<'a> {
@@ -25,17 +27,17 @@ impl<'a> From<&'a str> for ColumnRef<'a> {
2527
}
2628

2729
impl<'a> ToSqlTokens<'a> for ColumnRef<'a> {
28-
fn to_tokens(&self, out: &mut Vec<SqlToken<'a>>) {
30+
fn to_tokens(&self, out: &mut SqlTokens<'a>) {
2931
if let Some(table_ref) = self.table {
30-
out.push(SqlToken::new_ident(table_ref));
31-
out.push(SqlToken::Symbol(Dot))
32+
out.ident(table_ref);
33+
out.symbol(Dot)
3234
}
3335

34-
out.push(SqlToken::new_ident(self.column));
36+
out.ident(self.column);
3537

3638
if let Some(alias) = self.alias {
37-
out.push(SqlToken::new_keyword("AS"));
38-
out.push(SqlToken::new_ident(alias));
39+
out.keyword(Keyword::As);
40+
out.ident(alias);
3941
}
4042
}
4143
}
@@ -70,7 +72,7 @@ impl<'a> ColumnRef<'a> {
7072
mod __impl {
7173
use crate::query::querybuilder::syntax::column::{__detail, ColumnRef};
7274

73-
pub(crate) fn column_ref_from_str_ref(value: &'_ str) -> ColumnRef<'_> {
75+
pub(crate) fn column_ref_from_str_ref(value: &str) -> ColumnRef {
7476
let trimmed = value.trim();
7577

7678
let (before_alias, alias) = match __detail::find_case_insensitive_as(trimmed) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
/// Governs syntax rules such as placeholder format,
3+
/// quoting style, and supported clauses.
4+
/// For example, PostgreSQL may allow `RETURNING`, while MySQL does not.
5+
pub trait SqlDialect {
6+
const SUPPORTS_RETURNING: bool = true;
7+
const SUPPORTS_LIMIT_OFFSET: bool = true;
8+
// const IDENT_QUOTING: IdentQuoting;
9+
}
10+
11+
#[cfg(feature = "postgres")]
12+
pub struct PgDialect;
13+
#[cfg(feature = "postgres")] impl SqlDialect for PgDialect {}
14+
15+
#[cfg(feature = "mssql")]
16+
pub struct MsSql;
17+
#[cfg(feature = "mssql")] impl SqlDialect for MsSql {
18+
const SUPPORTS_RETURNING: bool = false;
19+
}
20+
#[cfg(feature = "mysql")]
21+
pub struct MySql;
22+
#[cfg(feature = "mysql")] impl SqlDialect for MySql {}

0 commit comments

Comments
 (0)