Skip to content

Commit

Permalink
Merge pull request #254 from Qrlew/fix_mssql_translator
Browse files Browse the repository at this point in the history
Fix mssql translator
  • Loading branch information
ngrislain authored Jan 18, 2024
2 parents e15afc8 + ab68376 commit abe4744
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 56 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed

## [0.9.5] - 2024-01-18
### Fixed
- bug mssql translator [#254](https://github.com/Qrlew/qrlew/pull/254)

## [0.9.5] - 2024-01-17
- Fixed [#251](https://github.com/Qrlew/qrlew/issues/251) and [#252](https://github.com/Qrlew/qrlew/issues/252)

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
authors = ["Nicolas Grislain <ng@sarus.tech>"]
name = "qrlew"
version = "0.9.5"
version = "0.9.6"
edition = "2021"
description = "Sarus Qrlew Engine"
documentation = "https://docs.rs/qrlew"
Expand Down
58 changes: 52 additions & 6 deletions src/dialect_translation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,6 @@ macro_rules! relation_to_query_tranlator_trait_constructor {
UnixTimestamp,
Quarter,
Date,
IsNull,
Min,
Max,
Median,
Expand All @@ -570,13 +569,11 @@ macro_rules! relation_to_query_tranlator_trait_constructor {

nary_function_ast_constructor!(
Pow,
Position,
Least,
Greatest,
Coalesce,
Rtrim,
Ltrim,
Substr,
Round,
Trunc,
RegexpContains,
Expand All @@ -585,10 +582,7 @@ macro_rules! relation_to_query_tranlator_trait_constructor {
FromUnixtime,
DateFormat,
Choose,
Like,
Ilike,
IsBool,
SubstrWithSize,
RegexpExtract,
RegexpReplace,
DatetimeDiff,
Expand Down Expand Up @@ -640,6 +634,58 @@ macro_rules! relation_to_query_tranlator_trait_constructor {
let arg = self.expr(expr);
function_builder("VARIANCE", vec![arg], true)
}
fn position(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 2);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Position {
expr: Box::new(ast_exprs[0].clone()),
r#in: Box::new(ast_exprs[1].clone()),
}
}
fn substr(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 3);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Substring {
expr: Box::new(ast_exprs[0].clone()),
substring_from: Some(Box::new(ast_exprs[1].clone())),
substring_for: Some(Box::new(ast_exprs[2].clone())),
special: false,
}
}
fn substr_with_size(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 3);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Substring {
expr: Box::new(ast_exprs[0].clone()),
substring_from: Some(Box::new(ast_exprs[1].clone())),
substring_for: Some(Box::new(ast_exprs[2].clone())),
special: false,
}
}
fn is_null(&self, expr: &expr::Expr) -> ast::Expr {
let ast_expr: ast::Expr = self.expr(expr);
ast::Expr::IsNull(Box::new(ast_expr))
}
fn ilike(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 2);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::ILike {
negated: false,
expr: Box::new(ast_exprs[0].clone()),
pattern: Box::new(ast_exprs[1].clone()),
escape_char: None,
}
}
fn like(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 2);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Like {
negated: false,
expr: Box::new(ast_exprs[0].clone()),
pattern: Box::new(ast_exprs[1].clone()),
escape_char: None,
}
}
}
};
}
Expand Down
34 changes: 32 additions & 2 deletions src/dialect_translation/mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ impl RelationToQueryTranslator for MsSqlTranslator {
function_builder("LOG", vec![arg], false)
}

/// Converting RANDOM to RAND
/// Converting RANDOM to RAND(CHECKSUM(NEWID()))
fn random(&self) -> ast::Expr {
function_builder("RAND", vec![], false)
let new_id = function_builder("NEWID", vec![], false);
let check_sum = function_builder("CHECKSUM", vec![new_id], false);
function_builder("RAND", vec![check_sum], false)
}

/// Converting MD5(X) to CONVERT(VARCHAR(MAX), HASHBYTES('MD5', X), 2)
Expand Down Expand Up @@ -124,6 +126,34 @@ impl RelationToQueryTranslator for MsSqlTranslator {
ast::Expr::from(&casted_to_integer)
}

fn cast_as_text(&self,expr: &expr::Expr) -> ast::Expr {
let ast_expr = self.expr(expr);
ast::Expr::Cast {
expr: Box::new(ast_expr),
data_type: ast::DataType::Nvarchar(Some(255)),
format: None
}
}
fn substr(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 3);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Substring {
expr: Box::new(ast_exprs[0].clone()),
substring_from: Some(Box::new(ast_exprs[1].clone())),
substring_for: Some(Box::new(ast_exprs[2].clone())),
special: true,
}
}
fn substr_with_size(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 3);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Substring {
expr: Box::new(ast_exprs[0].clone()),
substring_from: Some(Box::new(ast_exprs[1].clone())),
substring_for: Some(Box::new(ast_exprs[2].clone())),
special: true,
}
}
fn ceil(&self, expr: &expr::Expr) -> ast::Expr {
let arg = self.expr(expr);
function_builder("CEILING", vec![arg], false)
Expand Down
47 changes: 0 additions & 47 deletions src/dialect_translation/postgresql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,53 +83,6 @@ impl RelationToQueryTranslator for PostgreSqlTranslator {
null_treatment: None,
})
}

fn position(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 2);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Position {
expr: Box::new(ast_exprs[0].clone()),
r#in: Box::new(ast_exprs[1].clone()),
}
}

fn substr_with_size(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 3);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Substring {
expr: Box::new(ast_exprs[0].clone()),
substring_from: Some(Box::new(ast_exprs[1].clone())),
substring_for: Some(Box::new(ast_exprs[2].clone())),
special: false,
}
}

fn is_null(&self, expr: &expr::Expr) -> ast::Expr {
let ast_expr: ast::Expr = self.expr(expr);
ast::Expr::IsNull(Box::new(ast_expr))
}

fn ilike(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 2);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::ILike {
negated: false,
expr: Box::new(ast_exprs[0].clone()),
pattern: Box::new(ast_exprs[1].clone()),
escape_char: None,
}
}

fn like(&self, exprs: Vec<&expr::Expr>) -> ast::Expr {
assert!(exprs.len() == 2);
let ast_exprs: Vec<ast::Expr> = exprs.into_iter().map(|expr| self.expr(expr)).collect();
ast::Expr::Like {
negated: false,
expr: Box::new(ast_exprs[0].clone()),
pattern: Box::new(ast_exprs[1].clone()),
escape_char: None,
}
}
}

impl QueryToRelationTranslator for PostgreSqlTranslator {
Expand Down
5 changes: 5 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ fn test_on_postgresql() {

#[cfg(feature = "mssql")]
const QUERIES_FOR_MSSQL: &[&str] = &[
"SELECT RANDOM(), * FROM table_2",
"SELECT AVG(x) as a FROM table_2",
"SELECT 1+count(y) as a, sum(1+x) as b FROM table_2",
"SELECT 1+SUM(a), count(b) FROM table_1",
Expand Down Expand Up @@ -255,6 +256,10 @@ const QUERIES_FOR_MSSQL: &[&str] = &[
SELECT * FROM t1 UNION SELECT * FROM t2",
// Some joins
"SELECT * FROM order_table LEFT JOIN item_table on id=order_id WHERE price>10",
"SELECT SUBSTRING(z FROM 1 FOR 2) AS m, COUNT(*) AS my_count FROM table_2 GROUP BY z;",
"SELECT z AS age1, SUM(x) AS s1 FROM table_2 WHERE z IS NOT NULL GROUP BY z;",
"SELECT z, CASE WHEN z IS Null THEN 0 ELSE 1 END AS case_age, COUNT(*) AS c1 FROM table_2 GROUP BY z;",
"SELECT z, CASE WHEN z IS Null THEN CAST('A' AS VARCHAR(10)) ELSE CAST('B' AS VARCHAR(10)) END AS case_age, COUNT(*) AS c1 FROM table_2 GROUP BY z;",
// Some string functions
//"SELECT UPPER(z) FROM table_2 LIMIT 5",
//"SELECT LOWER(z) FROM table_2 LIMIT 5",
Expand Down

0 comments on commit abe4744

Please sign in to comment.