Skip to content

Commit bc6947c

Browse files
committed
refactor(WIP)!: querybuilder whitespaces();
1 parent 4d4920e commit bc6947c

38 files changed

Lines changed: 1342 additions & 317 deletions

canyon_core/src/connection/datasources.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ impl DatasourceConfig {
123123

124124
pub fn has_migrations_enabled(&self) -> bool {
125125
if let Some(migrations) = self.properties.migrations {
126+
// Option<Migrations>
126127
migrations.has_migrations_enabled()
127128
} else {
128129
false

canyon_core/src/connection/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ use crate::query::parameters::QueryParameter;
6060
use crate::rows::{CanyonRows, FromSqlOwnedValue};
6161

6262
// Apply the macro to implement DbConnection for &str and str
63-
use crate::impl_db_connection_for_str;
6463
impl_db_connection_for_str!(str);
6564
impl_db_connection_for_str!(&str);
6665

canyon_core/src/query/bounds.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::query::parameters::QueryParameter;
2+
use crate::query::querybuilder::syntax::column::ColumnRef;
23
use crate::rows::FromSqlOwnedValue;
34

45
/// Contract that provides a way to Canyon to inspect certain property or values at runtime.
@@ -66,11 +67,7 @@ pub trait TableMetadata<'a>: std::fmt::Display {
6667
pub trait FieldIdentifier: std::fmt::Display {
6768
fn as_str(&self) -> &'static str;
6869

69-
/// Returns a formatted string as `{<table_name>.<column_name>}`.
70-
///
71-
/// This is useful during queries generations for example, in join statements, when you
72-
/// alias other defined names, etc.
73-
fn table_and_column_name(&self) -> String;
70+
fn as_column_ref(&self) -> ColumnRef<'static>;
7471
}
7572

7673
/// Represents some kind of introspection to make the implementors

canyon_core/src/query/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ pub mod bounds;
55
pub mod operators;
66
pub mod parameters;
77
pub mod querybuilder;
8+
9+
// Re-exports
10+
pub use crate::query::querybuilder::syntax::column::ColumnRef;

canyon_core/src/query/operators.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::fmt::Display;
77

88
/// Enumerated type for represent the comparison operations
99
/// in SQL sentences
10-
#[derive(Debug, PartialEq, Copy, Clone)]
10+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1111
pub enum Comp {
1212
/// Operator "=" equals
1313
Eq,
@@ -40,7 +40,7 @@ impl Display for Comp {
4040
}
4141
}
4242

43-
impl<'a> ToSqlTokens<'a> for Comp {
43+
impl<'a, D: SqlDialect> ToSqlTokens<'a, D> for Comp {
4444
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
4545
let mut out = SqlTokens::with_capacity(2);
4646

@@ -67,7 +67,7 @@ impl<'a> ToSqlTokens<'a> for Comp {
6767
}
6868
}
6969

70-
#[derive(Debug, PartialEq, Copy, Clone)]
70+
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
7171
pub enum LikeKind {
7272
/// Operator "LIKE" as '%pattern%'
7373
Full,

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

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,6 @@ pub trait SelectQueryBuilderOps<'a>: QueryBuilderOps<'a> {
141141
/// without mixing types or polluting everything into
142142
/// just one type.
143143
pub trait QueryBuilderOps<'a> {
144-
/// Returns a read-only reference to the underlying SQL sentence,
145-
/// with the same lifetime as self
146-
// fn read_sql(&'a self) -> &'a str;
147-
148-
// /// Public interface for append the content of a slice to the end of
149-
// /// the underlying SQL sentence.
150-
// ///
151-
// /// This mutator will allow the user to wire SQL code to the already
152-
// /// generated one
153-
// ///
154-
// /// * `sql` - The [`&str`] to be wired in the SQL
155-
// fn push_sql(self, sql: &str);
156-
157144
/// Generates a `WHERE` SQL clause for constraint the query.
158145
///
159146
/// * `column` - An [`&str`] that will provide the target column name

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use crate::query::parameters::QueryParameter;
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;
1+
pub(crate) use crate::query::querybuilder::syntax::{
2+
column::ColumnRef, emitter::AstProcessor, query_kind::QueryKind,
3+
};
54
use transient::Transient;
65

76
#[derive(Default, Transient)]
@@ -17,7 +16,7 @@ impl<'a> AstProcessor<'a> for InsertAst<'a> {
1716
}
1817

1918
impl<'a> InsertAst<'a> {
20-
pub const fn new() -> Self {
19+
pub const fn _new() -> Self {
2120
Self {
2221
columns: Vec::new(),
2322
returning_columns: Vec::new(),

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::query::operators::Comp;
22
use crate::query::querybuilder::syntax::column::ColumnRef;
3+
use crate::query::querybuilder::syntax::dialect::SqlDialect;
34
use crate::query::querybuilder::syntax::keyword::Keyword;
45
use crate::query::querybuilder::syntax::tokens::{
56
PlaceholderKind, SqlToken, SqlTokens, ToSqlTokens,
@@ -31,19 +32,25 @@ impl From<ConditionClauseKind> for Keyword {
3132
}
3233
}
3334

34-
impl<'a> ToSqlTokens<'a> for ConditionClause<'a> {
35+
impl<'a, D: SqlDialect> ToSqlTokens<'a, D> for ConditionClause<'a> {
3536
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
3637
let mut out = SqlTokens::with_capacity(4);
3738

3839
// Clause keyword
3940
out.keyword(self.kind.into());
4041

4142
// Column
42-
out.extend(self.column_name.to_tokens());
43+
out.extend(<ColumnRef<'_> as ToSqlTokens<'_, D>>::to_tokens(
44+
&self.column_name,
45+
));
46+
47+
out.whitespace();
4348

4449
// Operator
4550
out.operator(self.operator);
4651

52+
out.whitespace();
53+
4754
// Value placeholder
4855
out.placeholder(match self.operator {
4956
Comp::Like(kind) => PlaceholderKind::Like(kind, self.value_index),

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::query::bounds::FieldIdentifier;
2+
use crate::query::querybuilder::syntax::dialect::SqlDialect;
23
use crate::query::querybuilder::syntax::tokens::{SqlToken, SqlTokens, ToSqlTokens};
34

45
#[derive(Debug, Clone, Default)]
@@ -10,10 +11,10 @@ pub struct ColumnRef<'a> {
1011

1112
impl<'a, T> From<T> for ColumnRef<'a>
1213
where
13-
T: FieldIdentifier,
14+
T: FieldIdentifier + 'a,
1415
{
1516
fn from(value: T) -> Self {
16-
Self::from(value.as_str())
17+
value.as_column_ref()
1718
}
1819
}
1920

@@ -23,10 +24,10 @@ impl<'a> From<&'a str> for ColumnRef<'a> {
2324
}
2425
}
2526

26-
impl<'a> ToSqlTokens<'a> for ColumnRef<'a> {
27+
impl<'a, D: SqlDialect> ToSqlTokens<'a, D> for ColumnRef<'a> {
2728
fn to_tokens(&self) -> impl IntoIterator<Item = SqlToken<'a>> + 'a {
2829
let mut out = SqlTokens::with_capacity(__detail::calculate_column_ref_capacity(self));
29-
__impl::generate_column_ref_tokens(self, &mut out);
30+
__impl::generate_column_ref_tokens::<D>(self, &mut out);
3031
out
3132
}
3233
}
@@ -60,6 +61,8 @@ impl<'a> ColumnRef<'a> {
6061

6162
mod __impl {
6263
use crate::query::querybuilder::syntax::column::{__detail, ColumnRef};
64+
use crate::query::querybuilder::syntax::dialect::SqlDialect;
65+
use crate::query::querybuilder::syntax::emitter::types::helpers;
6366
use crate::query::querybuilder::syntax::keyword::Keyword;
6467
use crate::query::querybuilder::syntax::symbol::Symbol::Dot;
6568
use crate::query::querybuilder::syntax::tokens::SqlTokens;
@@ -88,17 +91,20 @@ mod __impl {
8891
}
8992
}
9093

91-
pub(crate) fn generate_column_ref_tokens<'a>(__self: &ColumnRef<'a>, out: &mut SqlTokens<'a>) {
94+
pub(crate) fn generate_column_ref_tokens<'a, D: SqlDialect>(
95+
__self: &ColumnRef<'a>,
96+
out: &mut SqlTokens<'a>,
97+
) {
9298
if let Some(table_ref) = __self.table {
93-
out.ident(table_ref);
99+
helpers::push_quoted_ident::<D>(table_ref, out);
94100
out.symbol(Dot)
95101
}
96102

97-
out.ident(__self.column);
103+
helpers::push_quoted_ident::<D>(__self.column, out);
98104

99105
if let Some(alias) = __self.alias {
100106
out.keyword(Keyword::As);
101-
out.ident(alias);
107+
helpers::push_quoted_ident::<D>(alias, out);
102108
}
103109
}
104110
}

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

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ pub trait SqlDialect {
1212
const DB: DatabaseType;
1313
const SUPPORTS_RETURNING: bool = true;
1414
const _SUPPORTS_LIMIT_OFFSET: bool = true;
15-
const IDENT_QUOTING: IdentQuoting = IdentQuoting::DoubleQuote;
15+
const IDENT_QUOTING: IdentQuotingStyle = IdentQuotingStyle::DoubleQuote;
1616
const PLACEHOLDER_SYMBOL: PlaceholderSymbol = PlaceholderSymbol::DollarNumbered;
17-
const PLACEHOLDER_DATA_TYPE: PlaceholderDatatype = PlaceholderDatatype::VARCHAR;
17+
const PLACEHOLDER_DATA_TYPE: PlaceholderDatatype = PlaceholderDatatype::Varchar;
1818
}
1919

2020
/// Safe assuming that Canyon's default is PostgreSQL,
2121
/// which is the most widely used and standards-compliant database among the supported ones.
22+
#[allow(dead_code)]
2223
pub struct StandardDialect;
2324
impl SqlDialect for StandardDialect {
2425
const DB: DatabaseType = PostgreSql;
@@ -29,7 +30,7 @@ pub struct PgDialect;
2930
#[cfg(feature = "postgres")]
3031
impl SqlDialect for PgDialect {
3132
const DB: DatabaseType = PostgreSql;
32-
const IDENT_QUOTING: IdentQuoting = IdentQuoting::DoubleQuote;
33+
const IDENT_QUOTING: IdentQuotingStyle = IdentQuotingStyle::DoubleQuote;
3334
const PLACEHOLDER_SYMBOL: PlaceholderSymbol = PlaceholderSymbol::DollarNumbered;
3435
}
3536

@@ -39,7 +40,7 @@ pub struct MsSql;
3940
impl SqlDialect for MsSql {
4041
const DB: DatabaseType = SqlServer;
4142
const SUPPORTS_RETURNING: bool = false;
42-
const IDENT_QUOTING: IdentQuoting = IdentQuoting::Bracket;
43+
const IDENT_QUOTING: IdentQuotingStyle = IdentQuotingStyle::Bracket;
4344
const PLACEHOLDER_SYMBOL: PlaceholderSymbol = PlaceholderSymbol::AtPNumbered;
4445
}
4546

@@ -48,9 +49,9 @@ pub struct MySql;
4849
#[cfg(feature = "mysql")]
4950
impl SqlDialect for MySql {
5051
const DB: DatabaseType = MySQL;
51-
const IDENT_QUOTING: IdentQuoting = IdentQuoting::Backtick;
52+
const IDENT_QUOTING: IdentQuotingStyle = IdentQuotingStyle::Backtick;
5253
const PLACEHOLDER_SYMBOL: PlaceholderSymbol = PlaceholderSymbol::QuestionMark;
53-
const PLACEHOLDER_DATA_TYPE: PlaceholderDatatype = PlaceholderDatatype::CHAR;
54+
const PLACEHOLDER_DATA_TYPE: PlaceholderDatatype = PlaceholderDatatype::Char;
5455
}
5556

5657
/// Identifier quoting strategy for a SQL dialect.
@@ -65,7 +66,7 @@ impl SqlDialect for MySql {
6566
/// - MySQL: `` `ident` ``
6667
/// - SQL Server: `[ident]`
6768
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68-
pub enum IdentQuoting {
69+
pub enum IdentQuotingStyle {
6970
/// ANSI SQL style, used by PostgreSQL and as the generic default.
7071
DoubleQuote,
7172
/// MySQL style.
@@ -74,23 +75,43 @@ pub enum IdentQuoting {
7475
Bracket,
7576
}
7677

77-
impl IdentQuoting {
78+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79+
pub enum IdentQuoting {
80+
DoubleQuote,
81+
Backtick,
82+
OpeningBracket,
83+
ClosingBracket,
84+
}
85+
86+
impl IdentQuotingStyle {
7887
#[inline]
79-
pub const fn opening(self) -> &'static str {
88+
pub const fn opening(self) -> IdentQuoting {
8089
match self {
81-
Self::DoubleQuote => "\"",
82-
Self::Backtick => "`",
83-
Self::Bracket => "[",
90+
Self::DoubleQuote => IdentQuoting::DoubleQuote,
91+
Self::Backtick => IdentQuoting::Backtick,
92+
Self::Bracket => IdentQuoting::OpeningBracket,
8493
}
8594
}
8695

8796
#[inline]
88-
pub const fn closing(self) -> &'static str {
97+
pub const fn closing(self) -> IdentQuoting {
8998
match self {
99+
Self::DoubleQuote => IdentQuoting::DoubleQuote,
100+
Self::Backtick => IdentQuoting::Backtick,
101+
Self::Bracket => IdentQuoting::ClosingBracket,
102+
}
103+
}
104+
}
105+
106+
impl Display for IdentQuoting {
107+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108+
let t = match self {
90109
Self::DoubleQuote => "\"",
91110
Self::Backtick => "`",
92-
Self::Bracket => "]",
93-
}
111+
Self::OpeningBracket => "[",
112+
Self::ClosingBracket => "]",
113+
};
114+
write!(f, "{}", t)
94115
}
95116
}
96117

@@ -104,7 +125,7 @@ pub enum PlaceholderSymbol {
104125
/// @p1, @p2, @p3
105126
AtPNumbered,
106127
/// :1, :2, :3
107-
ColonNumbered,
128+
_ColonNumbered,
108129
}
109130

110131
impl Display for PlaceholderSymbol {
@@ -113,7 +134,7 @@ impl Display for PlaceholderSymbol {
113134
Self::QuestionMark => "?",
114135
Self::DollarNumbered => "$",
115136
Self::AtPNumbered => "@P",
116-
Self::ColonNumbered => ":",
137+
Self::_ColonNumbered => ":",
117138
};
118139
write!(f, "{}", symbol)
119140
}
@@ -122,15 +143,15 @@ impl Display for PlaceholderSymbol {
122143
/// Represents the syntax style for parameter placeholders in prepared statements.
123144
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
124145
pub enum PlaceholderDatatype {
125-
VARCHAR,
126-
CHAR,
146+
Varchar,
147+
Char,
127148
}
128149

129150
impl Display for PlaceholderDatatype {
130151
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131152
let datatype = match self {
132-
Self::VARCHAR => "VARCHAR",
133-
Self::CHAR => "CHAR",
153+
Self::Varchar => "VARCHAR",
154+
Self::Char => "CHAR",
134155
};
135156
write!(f, "{}", datatype)
136157
}

0 commit comments

Comments
 (0)