Skip to content

Commit e8ac267

Browse files
committed
refactor(WIP)!: emit_columns shared logic. New helpers mod for the shared emission impl details
1 parent 7bb4433 commit e8ac267

9 files changed

Lines changed: 57 additions & 62 deletions

File tree

canyon_core/src/connection/database_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub enum DatabaseType {
7171
/// .build()?; // resolved dynamically to the active database type
7272
/// ```
7373
#[default]
74-
Deferred,
74+
Deferred, // TODO: review if this is yet viable
7575
}
7676

7777
impl Display for DatabaseType {

canyon_core/src/query/querybuilder/syntax/emitter/backends/mysql.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,4 @@ pub struct MySqlEmitter<'a> {
99

1010
impl<'a> SqlEmitter<'a> for MySqlEmitter<'a> {
1111
type Dialect = MySql;
12-
13-
fn tokens(&mut self) -> &mut SqlTokens<'a> {
14-
&mut self.tokens
15-
}
1612
}
Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
use crate::query::querybuilder::syntax::ast::BaseAst;
21
use crate::query::querybuilder::syntax::dialect::PgDialect;
3-
use crate::query::querybuilder::syntax::emitter::types::select::EmitSelect;
42
use crate::query::querybuilder::syntax::emitter::{AstProcessor, SqlEmitter};
5-
use crate::query::querybuilder::syntax::query_kind::QueryKind;
63
use crate::query::querybuilder::syntax::tokens::SqlTokens;
74

85
#[derive(Default)]
@@ -14,8 +11,4 @@ pub struct PgEmitter<'a> {
1411
// implementation is based on the postgres one, that's why postgres doesn't override it
1512
impl<'a> SqlEmitter<'a> for PgEmitter<'a> {
1613
type Dialect = PgDialect;
17-
18-
fn tokens(&mut self) -> &mut SqlTokens<'a> {
19-
&mut self.tokens
20-
}
2114
}

canyon_core/src/query/querybuilder/syntax/emitter/mod.rs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,6 @@ where
8383
/// system.
8484
type Dialect: SqlDialect;
8585

86-
/// Mutable access to the internal SQL token buffer.
87-
///
88-
/// SQL emission produces a sequence of tokens such as keywords,
89-
/// symbols, identifiers, and parameter placeholders. Emitters write
90-
/// these tokens into the buffer during `emit`. After emission is
91-
/// complete, the buffer can be passed to a renderer to produce
92-
/// a final SQL string.
93-
fn tokens(&mut self) -> &mut SqlTokens<'a>;
94-
9586
/// Emit SQL tokens for the given AST node and table metadata.
9687
///
9788
/// This method is the central entry point for query emission.
@@ -116,28 +107,28 @@ where
116107
/// emission writes: `SELECT ... FROM ... WHERE ...`. A backend
117108
/// emitter may choose to include or omit certain clauses (e.g.,
118109
/// `RETURNING`) depending on dialect support.
119-
fn emit(&mut self, ast: &impl AstProcessor<'a>, base_ast: &BaseAst<'a>)
110+
fn emit(&mut self, ast: &impl AstProcessor<'a>, base_ast: &BaseAst<'a>) -> SqlTokens<'a>
120111
where
121112
Self: Sized,
122113
{
123114
// Default implementation delegates:
124115
match ast.query_kind() {
125116
QueryKind::Select => self.emit_select(ast, base_ast),
126-
QueryKind::Insert => {}
127-
QueryKind::Update => {}
128-
QueryKind::Delete => {}
117+
QueryKind::Insert => self.emit_select(ast, base_ast),
118+
QueryKind::Update => self.emit_select(ast, base_ast),
119+
QueryKind::Delete => self.emit_select(ast, base_ast),
129120
}
130121
} // TODO: should emit as the outer wrapper really return the emitter internal buffer?
131122
}
132123

133124
pub trait EmitInsert<'a>: SqlEmitter<'a> {
134-
fn emit_insert(&mut self, ast: &'a InsertAst<'a>, meta: &TableMetadata<'a>);
125+
fn emit_insert(&mut self, ast: &'a InsertAst<'a>, meta: &TableMetadata<'a>) -> SqlTokens<'a>;
135126
}
136127

137128
pub trait EmitUpdate<'a>: SqlEmitter<'a> {
138-
fn emit_update(&mut self, ast: &'a UpdateAst<'a>, meta: &TableMetadata<'a>);
129+
fn emit_update(&mut self, ast: &'a UpdateAst<'a>, meta: &TableMetadata<'a>) -> SqlTokens<'a>;
139130
}
140131

141132
pub trait EmitDelete<'a>: SqlEmitter<'a> {
142-
fn emit_delete(&mut self, ast: &'a DeleteAst, meta: &TableMetadata<'a>);
133+
fn emit_delete(&mut self, ast: &'a DeleteAst, meta: &TableMetadata<'a>) -> SqlTokens<'a>;
143134
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//! Standalone functions that shares the same behaviour for different AST kinds
2+
3+
use crate::query::querybuilder::syntax::column::ColumnRef;
4+
use crate::query::querybuilder::syntax::symbol::Symbol::Comma;
5+
use crate::query::querybuilder::syntax::tokens::{SqlTokens, ToSqlTokens};
6+
7+
pub(crate) fn emit_columns<'a>(columns: &Vec<ColumnRef<'a>>, tokens: &mut SqlTokens<'a>) {
8+
for (i, column) in columns.iter().enumerate() {
9+
if i > 0 {
10+
tokens.symbol(Comma);
11+
}
12+
column.to_tokens(tokens); // TODO: change opt-out-in
13+
}
14+
}
Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
use crate::query::querybuilder::syntax::ast::insert::InsertAst;
22
use crate::query::querybuilder::syntax::dialect::SqlDialect;
33
use crate::query::querybuilder::syntax::emitter::SqlEmitter;
4+
use crate::query::querybuilder::syntax::emitter::types::helpers;
45
use crate::query::querybuilder::syntax::keyword::Keyword;
5-
use crate::query::querybuilder::syntax::symbol::Symbol::Comma;
6-
use crate::query::querybuilder::syntax::tokens::ToSqlTokens;
6+
use crate::query::querybuilder::syntax::tokens::SqlTokens;
77

8-
pub(crate) fn emit_returning<'a, E: SqlEmitter<'a>>(emitter: &mut E, ast: &InsertAst<'a>) {
8+
pub(crate) fn emit_returning<'a, E: SqlEmitter<'a>>(
9+
ast: &InsertAst<'a>,
10+
tokens: &mut SqlTokens<'a>,
11+
) {
912
if !E::Dialect::SUPPORTS_RETURNING {
1013
return; // early guarding
1114
}
1215
// TODO: actual impl, not the one below, is should have a RETURNING COLS on the INSERT implementation
13-
let tokens_holder = emitter.tokens();
14-
tokens_holder.keyword(Keyword::Returning);
15-
16-
for (i, column) in ast.columns.iter().enumerate() {
17-
// TODO:: this is duplicated
18-
if i > 0 {
19-
tokens_holder.symbol(Comma);
20-
}
21-
column.to_tokens(tokens_holder); // TODO: strange
22-
}
16+
tokens.keyword(Keyword::Returning);
17+
// add the columns
18+
helpers::emit_columns(&ast.columns, tokens)
2319
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub(crate) mod delete;
2+
mod helpers;
23
pub(crate) mod insert;
34
pub(crate) mod select;
45
pub(crate) mod update;
Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,46 @@
1-
use crate::query::querybuilder::syntax::ast::BaseAst;
21
use crate::query::querybuilder::syntax::ast::select::SelectAst;
2+
use crate::query::querybuilder::syntax::ast::BaseAst;
3+
use crate::query::querybuilder::syntax::emitter::types::helpers;
34
use crate::query::querybuilder::syntax::emitter::{AstProcessor, SqlEmitter};
45
use crate::query::querybuilder::syntax::keyword::Keyword;
5-
use crate::query::querybuilder::syntax::symbol::Symbol::Comma;
6-
use crate::query::querybuilder::syntax::tokens::{SqlTokens, ToSqlTokens};
6+
use crate::query::querybuilder::syntax::tokens::SqlTokens;
77

88
/// Blanket implementation for all the SqlEmitter implementors that are able to generate
99
/// SELECT like SQL clauses
1010
impl<'a, T> EmitSelect<'a> for T
1111
where
1212
T: SqlEmitter<'a>,
1313
{
14-
fn emit_select(&mut self, ast: &impl AstProcessor<'a>, base_ast: &BaseAst<'a>) {
15-
let select_ast = transient::Downcast::downcast_ref::<SelectAst>(ast.as_any()).expect("Handle this");
16-
self.tokens().keyword(Keyword::Select);
14+
fn emit_select(
15+
&mut self,
16+
ast: &impl AstProcessor<'a>,
17+
base_ast: &BaseAst<'a>,
18+
) -> SqlTokens<'a> {
19+
let mut tokens = SqlTokens::default();
20+
21+
let select_ast =
22+
transient::Downcast::downcast_ref::<SelectAst>(ast.as_any()).expect("Handle this");
1723

18-
emit_columns(self, select_ast);
19-
emit_from(self, base_ast);
24+
tokens.keyword(Keyword::Select);
25+
26+
emit_columns(select_ast, &mut tokens);
27+
emit_from(base_ast, &mut tokens);
28+
29+
tokens
2030
}
2131
}
2232

2333
/// DOC me this
2434
pub trait EmitSelect<'a>: SqlEmitter<'a> {
25-
fn emit_select(&mut self, ast: &impl AstProcessor<'a>, base_ast: &BaseAst<'a>);
35+
fn emit_select(&mut self, ast: &impl AstProcessor<'a>, base_ast: &BaseAst<'a>)
36+
-> SqlTokens<'a>;
2637
}
2738

28-
pub(crate) fn emit_columns<'a>(emitter: &mut impl SqlEmitter<'a>, ast: &SelectAst<'a>) {
29-
let tokens = emitter.tokens();
30-
for (i, column) in ast.columns.iter().enumerate() {
31-
if i > 0 {
32-
tokens.symbol(Comma);
33-
}
34-
column.to_tokens(tokens);
35-
}
39+
pub(crate) fn emit_columns<'a>(ast: &SelectAst<'a>, tokens: &mut SqlTokens<'a>) {
40+
helpers::emit_columns(&ast.columns, tokens)
3641
}
3742

38-
pub(crate) fn emit_from<'a>(emitter: &mut impl SqlEmitter<'a>, base_ast: &BaseAst<'a>) {
43+
pub(crate) fn emit_from<'a>(base_ast: &BaseAst<'a>, tokens: &mut SqlTokens<'a>) {
3944
//meta.to_tokens(emitter.tokens())
4045
todo!()
4146
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'a, P: AstProcessor<'a> + 'a> QueryBuilder<'a, P> {
4848
}
4949

5050
fn sql<'b>(&self) -> Result<String, Box<dyn Error + Send + Sync + 'b>> {
51-
// __impl::check_invariants_over_condition_clauses(self)?;
51+
__impl::check_invariants_over_condition_clauses(self)?;
5252

5353
let mut tokens = SqlTokens::default();
5454

@@ -167,7 +167,7 @@ mod __impl {
167167
/// Quick standalone that acts as a façade for an orchestrator that just organizes a procedural way of testing
168168
/// that the constructed underlying query is syntactically correct
169169
pub(crate) fn check_invariants_over_condition_clauses<'a, 'b, P: AstProcessor<'a>>(
170-
_self: &'a QueryBuilder<'a, P>,
170+
_self: &QueryBuilder<'a, P>,
171171
) -> Result<(), Box<dyn Error + Send + Sync + 'b>> {
172172
__validators::check_where_clause_position(_self)
173173
}
@@ -231,7 +231,6 @@ mod __detail {
231231
) where
232232
P: AstProcessor<'a>,
233233
{
234-
let qk = ast.query_kind();
235234
match database_type {
236235
DatabaseType::PostgreSql => {
237236
let mut emitter = PgEmitter::default();

0 commit comments

Comments
 (0)