Skip to content

Commit

Permalink
Merge pull request #259 from Qrlew/fit_case_insensitivness
Browse files Browse the repository at this point in the history
Fit queries with unquoted uppercase identifiers
  • Loading branch information
ngrislain authored Jan 29, 2024
2 parents c81fcc1 + d73b583 commit 839c117
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 48 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.9] - 2024-01-28
### Fixed
- Fix queries with uppercase un-quoted identifiers.

## [0.9.8] - 2024-01-28
### Added
- Added mutiplicity parameters to DP
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 <[email protected]>"]
name = "qrlew"
version = "0.9.8"
version = "0.9.9"
edition = "2021"
description = "Sarus Qrlew Engine"
documentation = "https://docs.rs/qrlew"
Expand Down
4 changes: 2 additions & 2 deletions src/dialect_translation/mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,12 @@ impl RelationToQueryTranslator for MsSqlTranslator {
global: None,
if_not_exists: false,
transient: false,
name: table.path().clone().into(),
name: ast::ObjectName(self.identifier( &(table.path().clone().into()) )),
columns: table
.schema()
.iter()
.map(|f| ast::ColumnDef {
name: f.name().into(),
name: self.identifier( &(f.name().into()) )[0].clone(),
// Need to override some convertions
data_type: { translate_data_type(f.data_type()) },
collation: None,
Expand Down
10 changes: 6 additions & 4 deletions src/dialect_translation/postgresql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,21 @@ mod tests {
)
.build();
let relations = Hierarchy::from([(["schema", "MY SPECIAL TABLE"], Arc::new(table))]);
let query_str = r#"SELECT "Id", normal_col, "Na.Me" FROM schema."MY SPECIAL TABLE""#;
let query_str = r#"SELECT "Id", NORMAL_COL, "Na.Me" FROM "MY SPECIAL TABLE" ORDER BY "Id" "#;
let translator = PostgreSqlTranslator;
let query = parse_with_dialect(query_str, translator.dialect())?;
let query_with_relation = QueryWithRelations::new(&query, &relations);
let relation = Relation::try_from((query_with_relation, translator))?;

println!("\n {} \n", relation);
let rel_with_traslator = RelationWithTranslator(&relation, translator);
let retranslated = ast::Query::from(rel_with_traslator);
print!("{}", retranslated);
let translated = r#"
WITH "map_mou5" ("Id", "normal_col", "Na.Me") AS (
WITH "map_mou5" ("Id","normal_col","Na.Me") AS (
SELECT "Id" AS "Id", "normal_col" AS "normal_col", "Na.Me" AS "Na.Me" FROM "MY SPECIAL TABLE"
) SELECT * FROM "map_mou5"
), "map_0swv"("Id","normal_col","Na.Me") AS (
SELECT "Id" AS "Id", "normal_col" AS "normal_col", "Na.Me" AS "Na.Me" FROM "map_mou5" ORDER BY "Id" ASC
) SELECT * FROM "map_0swv"
"#;
assert_same_query_str(&retranslated.to_string(), translated);
Ok(())
Expand Down
43 changes: 31 additions & 12 deletions src/io/bigquery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,19 @@ impl Database {
.with(("income", DataType::float_interval(100.0, 200000.0))),
)
.build(),
// TODO: create table with names that need to be quoted
TableBuilder::new()
.path(["MY_SPECIAL_TABLE"])
.name("my_table")
.size(100)
.schema(
Schema::empty()
.with(("Id", DataType::integer_interval(0, 1000)))
.with(("Na.Me", DataType::text()))
.with(("inc&ome", DataType::float_interval(100.0, 200000.0)))
.with(("normal_col", DataType::text())),
)
.build(),
]
}
}
Expand Down Expand Up @@ -454,6 +467,7 @@ impl DatabaseTrait for Database {
fn create_table(&mut self, table: &Table) -> Result<usize> {
let mut rt = tokio::runtime::Runtime::new()?;
let bq_table: BQTable = table.clone().try_into()?;

rt.block_on(self.client.table().create(bq_table))?;
Ok(1)
}
Expand Down Expand Up @@ -486,6 +500,7 @@ impl DatabaseTrait for Database {
json: map_as_json,
});
}

insert_query.add_rows(rows_for_bq.clone())?;

rt.block_on(self.client.tabledata().insert_all(
Expand Down Expand Up @@ -975,19 +990,15 @@ mod tests {
println!("Datetime: {:?}", time);
}

// #[test]
// fn test_create_table() {
// let mut rt = tokio::runtime::Runtime::new().unwrap();

// let (auth_server, tmp_file_credentials) = rt.block_on(build_auth()).unwrap();
// let client = rt
// .block_on(build_client(auth_server.uri(), &tmp_file_credentials))
// .unwrap();
// #[tokio::test]
// async fn test_create_table() {
// let (auth_server, tmp_file_credentials) = build_auth().await.unwrap();
// let client = build_client(auth_server.uri(), &tmp_file_credentials).await.unwrap();

// let table_name = "mytable5";
// let table_name = "MY TABLE";
// let table: Table = TableBuilder::new()
// .path(["dataset1", table_name])
// .name(table_name)
// .path([table_name])
// .name("aaaa")
// .size(10)
// .schema(
// Schema::empty()
Expand All @@ -998,7 +1009,8 @@ mod tests {
// .build();

// let bq_table: BQTable = table.try_into().unwrap();
// let res = rt.block_on(client.table().create(bq_table)).unwrap();
// println!("{:?}",bq_table);
// let res = (client.table().create(bq_table)).await.unwrap();
// println!("ROWS: {:?}", res.num_rows);
// // rt.block_on(client
// // .table()
Expand Down Expand Up @@ -1204,6 +1216,13 @@ mod tests {
for row in database.query(query)? {
println!("{}", row);
}

let query = r"SELECT * FROM my_special_table LIMIT 10";
println!("\n{query}");
for row in database.query(query)? {
println!("{}", row);
}

Ok(())
}
}
3 changes: 2 additions & 1 deletion src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ pub trait Database: Sized {
Schema::empty()
.with(("Id", DataType::integer_interval(0, 1000)))
.with(("Na.Me", DataType::text()))
.with(("inc&ome", DataType::float_interval(100.0, 200000.0))),
.with(("inc&ome", DataType::float_interval(100.0, 200000.0)))
.with(("normal_col", DataType::text())),
)
.build(),
]
Expand Down
21 changes: 21 additions & 0 deletions src/io/mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,19 @@ impl Database {
.with(("income", DataType::float_interval(100.0, 200000.0))),
)
.build(),
// TODO: create table with names that need to be quoted
TableBuilder::new()
.path(["MY SPECIAL TABLE"])
.name("my_table")
.size(100)
.schema(
Schema::empty()
.with(("Id", DataType::integer_interval(0, 1000)))
.with(("Na.Me", DataType::text()))
.with(("inc&ome", DataType::float_interval(100.0, 200000.0)))
.with(("normal_col", DataType::text())),
)
.build(),
]
}
}
Expand Down Expand Up @@ -324,6 +337,7 @@ impl DatabaseTrait for Database {
let rt = tokio::runtime::Runtime::new().unwrap();
let translator = MsSqlTranslator;
let create_table_query = &table.create(translator).to_string();

let query = sqlx::query(&create_table_query[..]);
let res = rt.block_on(async_execute(query, &self.pool))?;
Ok(res.rows_affected() as usize)
Expand All @@ -347,6 +361,7 @@ impl DatabaseTrait for Database {
for value in &values {
insert_query = insert_query.bind(value);
}

rt.block_on(async_execute(insert_query, &self.pool))?;
}
Ok(())
Expand Down Expand Up @@ -695,6 +710,12 @@ mod tests {
println!("{}", row);
}

let query = r#"SELECT TOP (10) * FROM "MY SPECIAL TABLE""#;
println!("\n{query}");
for row in database.query(query)? {
println!("{}", row);
}

Ok(())
}
}
2 changes: 1 addition & 1 deletion src/relation/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl<'a, T: RelationToQueryTranslator> Visitor<'a, ast::Query> for FromRelationV
map.order_by
.iter()
.map(|OrderBy { expr, asc }| ast::OrderByExpr {
expr: expr.into(),
expr: self.translator.expr(expr),
asc: Some(*asc),
nulls_first: None,
})
Expand Down
15 changes: 13 additions & 2 deletions src/sql/relation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,20 @@ impl<'a, T: QueryToRelationTranslator + Copy + Clone> VisitedQueryRelations<'a,
ast::SelectItem::UnnamedExpr(expr) => named_exprs.push((
match expr {
// Pull the original name for implicit aliasing
ast::Expr::Identifier(ident) => ident.value.clone(),
ast::Expr::Identifier(ident) => {
if let Some(_) = ident.quote_style {
ident.value.clone()
} else {
ident.value.to_lowercase()
}
},
ast::Expr::CompoundIdentifier(idents) => {
idents.last().unwrap().value.clone()
let iden = idents.last().unwrap();
if let Some(_) = iden.quote_style {
iden.value.clone()
} else {
iden.value.to_lowercase()
}
}
expr => namer::name_from_content(FIELD, &expr),
},
Expand Down
28 changes: 3 additions & 25 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ const POSTGRESQL_QUERIES: &[&str] = &[
"SELECT z AS age1, SUM(x) AS s1 FROM table_2 WHERE z IS NOT NULL GROUP BY z;",
"SELECT COUNT(*) AS c1 FROM table_2 WHERE y ILIKE '%ab%';",
"SELECT z, CASE WHEN z IS Null THEN 'Null' ELSE 'NotNull' END AS case_age, COUNT(*) AS c1 FROM table_2 GROUP BY z;",
r#"SELECT "Id", NORMAL_COL, "Na.Me" FROM "MY SPECIAL TABLE""#,
// This fails consistency tests due to numeric errors. It could be fixed with Round
// but in psql round(arg, precision) fails if arg is a double precision type
// "SELECT
Expand Down Expand Up @@ -287,6 +288,7 @@ const MSSQL_QUERIES: &[&str] = &[
// "WITH t1 AS (SELECT a, b, c FROM table_1 WHERE a > 5), t2 AS (SELECT a, d, c FROM table_1 WHERE a < 7 LIMIT 10) SELECT * FROM t1 NATURAL LEFT JOIN t2",
// "WITH t1 AS (SELECT a, b, c FROM table_1 WHERE a > 5), t2 AS (SELECT a, d, c FROM table_1 WHERE a < 7 LIMIT 10) SELECT * FROM t1 NATURAL RIGHT JOIN t2",
// "WITH t1 AS (SELECT a, b, c FROM table_1 WHERE a > 5), t2 AS (SELECT a, d, c FROM table_1 WHERE a < 7 LIMIT 10) SELECT * FROM t1 NATURAL FULL JOIN t2",
r#"SELECT "Id", NORMAL_COL, "Na.Me" FROM "MY SPECIAL TABLE""#,
];

#[cfg(feature = "mssql")]
Expand Down Expand Up @@ -400,6 +402,7 @@ fn test_on_bigquery() {
"WITH t1 AS (SELECT a, b, c FROM table_1 WHERE a > 5), t2 AS (SELECT a, d, c FROM table_1 WHERE a < 7 LIMIT 10) SELECT * FROM t1 NATURAL LEFT JOIN t2",
"WITH t1 AS (SELECT a, b, c FROM table_1 WHERE a > 5), t2 AS (SELECT a, d, c FROM table_1 WHERE a < 7 LIMIT 10) SELECT * FROM t1 NATURAL RIGHT JOIN t2",
"WITH t1 AS (SELECT a, b, c FROM table_1 WHERE a > 5), t2 AS (SELECT a, d, c FROM table_1 WHERE a < 7 LIMIT 10) SELECT * FROM t1 NATURAL FULL JOIN t2",
r#"SELECT "Id", NORMAL_COL, "Na.Me" FROM MY_SPECIAL_TABLE"#,
];
for &query in queries_for_bq.iter() {
println!("TESTING QUERY: {}", query);
Expand Down Expand Up @@ -441,28 +444,3 @@ fn test_distinct_aggregates() {
let rewriten_query: &str = &ast::Query::from(&distinct_rel).to_string();
assert!(test_eq(&mut database, true_query, rewriten_query));
}

#[test]
fn test_quoting() {
let mut database = postgresql::test_database();
let relations = database.relations();
let table = database
.relations()
.get(&["MY SPECIAL TABLE".to_string()])
.unwrap()
.as_ref()
.clone();

let true_query = r#"SELECT * FROM "MY SPECIAL TABLE""#;
let translator = PostgreSqlTranslator;
let query = parse_with_dialect(true_query, translator.dialect()).unwrap();
let query_with_relation = QueryWithRelations::new(&query, &relations);
let relation = Relation::try_from((query_with_relation, translator)).unwrap();

let rel_with_traslator = RelationWithTranslator(&relation, translator);
let retranslated = ast::Query::from(rel_with_traslator);
print!("{}", retranslated);
println!(
"{}", database .query(true_query).unwrap().iter().map(ToString::to_string).join("\n")
);
}

0 comments on commit 839c117

Please sign in to comment.