Skip to content

Commit

Permalink
ok
Browse files Browse the repository at this point in the history
  • Loading branch information
andicuko committed Jun 19, 2024
1 parent 4b30cdc commit 82c0690
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 16 deletions.
45 changes: 44 additions & 1 deletion src/data_type/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1944,6 +1944,17 @@ pub fn extract_year() -> impl Function {
))
}

pub fn extract_epoch() -> impl Function {
Polymorphic::from((
Pointwise::univariate(data_type::DateTime::default(), DataType::integer(), |a| {
(a.and_utc().timestamp() as i64).into()
}),
Pointwise::univariate(data_type::Duration::default(), DataType::integer(), |a| {
(a.num_seconds()).into()
}),
))
}

pub fn extract_month() -> impl Function {
Polymorphic::from((
Pointwise::univariate(
Expand Down Expand Up @@ -2449,7 +2460,8 @@ pub fn count_distinct() -> impl Function {
Aggregate::from(
DataType::Any,
|values| (values.iter().cloned().collect::<HashSet<_>>().len() as i64).into(),
|(_dt, size)| Ok(data_type::Integer::from_interval(1, *size.max().unwrap())),
|(_dt, size)| Ok(size), // count(distinct x) can be 0
//Ok(data_type::Integer::from_interval(1, *size.max().unwrap()))},
),
// Optional implementation
Aggregate::from(
Expand Down Expand Up @@ -4316,6 +4328,37 @@ mod tests {

#[test]
fn test_extract() {
// epoch
println!("\nTest extract_epoch");
let fun = extract_epoch();
println!("type = {}", fun);
println!("domain = {}", fun.domain());
println!("co_domain = {}", fun.co_domain());
println!("data_type = {}", fun.data_type());

let set = DataType::date_time_values([
NaiveDate::from_ymd_opt(2016, 7, 8)
.unwrap()
.and_hms_opt(9, 10, 11)
.unwrap(),
NaiveDate::from_ymd_opt(2026, 7, 8)
.unwrap()
.and_hms_opt(9, 15, 11)
.unwrap(),
]);

let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::integer_values([1467969011, 1783502111]));

let set = DataType::duration_values([
chrono::Duration::hours(24),
chrono::Duration::seconds(100),
]);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::integer_values([86400, 100]));

// year
println!("\nTest extract_year");
let fun = extract_year();
Expand Down
4 changes: 3 additions & 1 deletion src/dialect_translation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ macro_rules! relation_to_query_tranlator_trait_constructor {
expr::Value::Bytes(_) => todo!(),
expr::Value::Struct(_) => todo!(),
expr::Value::Union(_) => todo!(),
expr::Value::Optional(optional_val) => match optional_val.as_deref() {
expr::Value::Optional(optional_val) => match optional_val.as_deref() {
Some(arg) => self.value(arg),
None => ast::Expr::Value(ast::Value::Null),
},
Expand Down Expand Up @@ -438,6 +438,7 @@ macro_rules! relation_to_query_tranlator_trait_constructor {
CastAsTime,
Sign,
Unhex,
ExtractEpoch,
ExtractYear,
ExtractMonth,
ExtractDay,
Expand Down Expand Up @@ -557,6 +558,7 @@ macro_rules! relation_to_query_tranlator_trait_constructor {
CastAsTime,
Sign,
Unhex,
ExtractEpoch,
ExtractYear,
ExtractMonth,
ExtractDay,
Expand Down
13 changes: 9 additions & 4 deletions src/dialect_translation/mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,15 @@ impl RelationToQueryTranslator for MsSqlTranslator {
function_builder("CEILING", vec![arg], false)
}

// fn from_extract_epoch(&self, expr: &expr::Expr) -> ast::Expr {
// //EXTRACT(EPOCH FROM col1) is not supported yet
// todo!()
// }
fn extract_epoch(&self, expr: &expr::Expr) -> ast::Expr {
let arg = self.expr(expr);
let second = ast::Expr::Identifier(ast::Ident {
value: "SECOND".to_string(),
quote_style: None,
});
let unix = ast::Expr::Value(ast::Value::SingleQuotedString("19700101".to_string()));
function_builder("DATEDIFF", vec![second, unix, arg], false)
}

// used during onboarding in order to have datetime with a proper format.
// This is not needed when we will remove the cast in string of the datetime
Expand Down
3 changes: 1 addition & 2 deletions src/dialect_translation/postgresql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,7 @@ mod tests {
fn test_relation_to_query_with_null_field() -> Result<()> {
let mut database = postgresql::test_database();
let relations = database.relations();
let query_str =
r#"SELECT CASE WHEN (1) > (2) THEN 1 ELSE NULL END AS "_PRIVACY_UNIT_", a AS a FROM table_1"#;
let query_str = r#"SELECT CASE WHEN (1) > (2) THEN 1 ELSE NULL END AS "_PRIVACY_UNIT_", a AS a FROM table_1"#;
let translator = PostgreSqlTranslator;
let query = parse_with_dialect(query_str, translator.dialect())?;
let query_with_relation = QueryWithRelations::new(&query, &relations);
Expand Down
4 changes: 4 additions & 0 deletions src/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub enum Function {
CurrentDate,
CurrentTime,
CurrentTimestamp,
ExtractEpoch,
ExtractYear,
ExtractMonth,
ExtractDay,
Expand Down Expand Up @@ -173,6 +174,7 @@ impl Function {
| Function::CastAsTime
| Function::Sign
| Function::Unhex
| Function::ExtractEpoch
| Function::ExtractYear
| Function::ExtractMonth
| Function::ExtractDay
Expand Down Expand Up @@ -276,6 +278,7 @@ impl Function {
| Function::Floor
| Function::Sign
| Function::Unhex
| Function::ExtractEpoch
| Function::ExtractYear
| Function::ExtractMonth
| Function::ExtractDay
Expand Down Expand Up @@ -431,6 +434,7 @@ impl fmt::Display for Function {
Function::CastAsTime => "cast_as_time",
Function::Sign => "sign",
Function::Unhex => "unhex",
Function::ExtractEpoch => "extract_epoch",
Function::ExtractYear => "extract_year",
Function::ExtractMonth => "extract_month",
Function::ExtractDay => "extract_day",
Expand Down
1 change: 1 addition & 0 deletions src/expr/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function_implementations!(
RegexpContains,
Encode,
Decode,
ExtractEpoch,
ExtractYear,
ExtractMonth,
ExtractDay,
Expand Down
1 change: 1 addition & 0 deletions src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ impl_unary_function_constructors!(
Floor,
Sign,
Unhex,
ExtractEpoch,
ExtractYear,
ExtractMonth,
ExtractDay,
Expand Down
14 changes: 13 additions & 1 deletion src/expr/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ impl<'a> expr::Visitor<'a, ast::Expr> for FromExprVisitor {
null_treatment: None,
within_group: vec![],
}),
expr::function::Function::ExtractEpoch => ast::Expr::Extract {
field: ast::DateTimeField::Epoch,
expr: arguments[0].clone().into(),
},
expr::function::Function::ExtractYear => ast::Expr::Extract {
field: ast::DateTimeField::Year,
expr: arguments[0].clone().into(),
Expand Down Expand Up @@ -1209,6 +1213,15 @@ mod tests {

#[test]
fn test_extract() {
// EXTRACT(EPOCH FROM col1)
let str_expr = "extract(epoch from col1)";
let ast_expr: ast::Expr = parse_expr(str_expr).unwrap();
let expr = Expr::try_from(&ast_expr).unwrap();
println!("expr = {}", expr);
let gen_expr = ast::Expr::from(&expr);
println!("ast::expr = {gen_expr}");
assert_eq!(gen_expr, ast_expr);

// EXTRACT(YEAR FROM col1)
let str_expr = "extract(year from col1)";
let ast_expr: ast::Expr = parse_expr(str_expr).unwrap();
Expand Down Expand Up @@ -1511,5 +1524,4 @@ mod tests {
let expr = Expr::try_from(ast_expr.with(&Hierarchy::empty())).unwrap();
println!("expr = {}", expr);
}

}
4 changes: 2 additions & 2 deletions src/sql/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,7 @@ impl<'a> Visitor<'a, Result<Expr>> for TryIntoExprVisitor<'a> {

fn extract(&self, field: &'a ast::DateTimeField, expr: Result<Expr>) -> Result<Expr> {
Ok(match field {
ast::DateTimeField::Epoch => Expr::extract_epoch(expr.clone()?),
ast::DateTimeField::Year => Expr::extract_year(expr.clone()?),
ast::DateTimeField::Month => Expr::extract_month(expr.clone()?),
ast::DateTimeField::Week(_) => Expr::extract_week(expr.clone()?),
Expand Down Expand Up @@ -1443,8 +1444,7 @@ mod tests {
println!("\nast::expr = {ast_expr}");
let expr = Expr::try_from(ast_expr.with(&Hierarchy::empty())).unwrap();
println!("expr = {}", expr);



assert_eq!(
ast::Expr::from(&expr).to_string(),
String::from(
Expand Down
45 changes: 42 additions & 3 deletions src/sql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,19 @@ pub use relation::{parse, parse_with_dialect};

#[cfg(test)]
mod tests {
use std::sync::Arc;

use itertools::Itertools;

use super::*;
use crate::{
ast,
builder::With,
display::Dot,
hierarchy::Hierarchy,
io::{postgresql, Database},
relation::{Relation, Variant as _},
DataType, Ready as _,
};

#[test]
Expand Down Expand Up @@ -300,6 +304,42 @@ mod tests {
relation.display_dot().unwrap();
}

#[test]
fn test_parse_queries_on_inf_sized_table() {
let table: Arc<Relation> = Arc::new(
crate::relation::TableBuilder::new()
.path(["table_1"])
.name("table_1")
.size(9223372036854775807)
.schema(
crate::relation::Schema::empty()
.with(("a", DataType::float_interval(0., 10.)))
.with(("b", DataType::optional(DataType::float_interval(-1., 1.))))
.with((
"c",
DataType::date_interval(
chrono::NaiveDate::from_ymd_opt(1980, 12, 06).unwrap(),
chrono::NaiveDate::from_ymd_opt(2023, 12, 06).unwrap(),
),
))
.with(("d", DataType::integer_interval(0, 10)))
.with(("sarus_privacy_unit", DataType::optional(DataType::id()))),
)
.build(),
);
let relations: Hierarchy<Arc<Relation>> = Hierarchy::from([(vec!["table_1"], table)]);

let query_str: &str = r#"
SELECT 0.1 * COUNT(DISTINCT sarus_privacy_unit) FROM table_1
"#;

let query = parse(query_str).unwrap();
println!("QUERY: {}", query);
let qwr = query.with(&relations);
let relation = Relation::try_from(qwr).unwrap();
relation.display_dot().unwrap()
}

#[test]
fn test_parsing_many_times() {
let mut database = postgresql::test_database();
Expand All @@ -309,8 +349,8 @@ mod tests {
let mut query = parse(query).unwrap();
println!("QUERY: {}", query);
let binding = database.relations();
for i in 0..5 {

for _i in 0..5 {
let qwr = query.with(&binding);
let relation = Relation::try_from(qwr).unwrap();
relation.display_dot().unwrap();
Expand All @@ -326,6 +366,5 @@ mod tests {

query = parse(query_str).unwrap();
}

}
}
5 changes: 3 additions & 2 deletions src/sql/relation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,6 @@ impl<'a, T: QueryToRelationTranslator + Copy + Clone> VisitedQueryRelations<'a,
.iter()
.map(|(p, i)| (i.deref(), p.last().unwrap().clone()))
.collect();

for field in from.schema().iter() {
let field_name = field.name().to_string();
let alias = new_aliases
Expand Down Expand Up @@ -539,7 +538,6 @@ impl<'a, T: QueryToRelationTranslator + Copy + Clone> VisitedQueryRelations<'a,
let (named_expr_from_select, new_columns) =
self.try_named_expr_columns_from_select_items(columns, select_items, &from)?;
named_exprs.extend(named_expr_from_select.into_iter());

// Prepare the GROUP BY
let group_by = match group_by {
ast::GroupByExpr::All => todo!(),
Expand All @@ -548,6 +546,7 @@ impl<'a, T: QueryToRelationTranslator + Copy + Clone> VisitedQueryRelations<'a,
.map(|e| self.translator.try_expr(e, columns))
.collect::<Result<Vec<Expr>>>()?,
};

// If the GROUP BY contains aliases, then replace them by the corresponding expression in `named_exprs`.
// Note that we mimic postgres behavior and support only GROUP BY alias column (no other expressions containing aliases are allowed)
// The aliases cannot be used in HAVING
Expand All @@ -564,6 +563,7 @@ impl<'a, T: QueryToRelationTranslator + Copy + Clone> VisitedQueryRelations<'a,
_ => x,
})
.collect::<Vec<_>>();

// Add the having in named_exprs
let having = if let Some(expr) = having {
let having_name = namer::name_from_content(FIELD, &expr);
Expand Down Expand Up @@ -644,6 +644,7 @@ impl<'a, T: QueryToRelationTranslator + Copy + Clone> VisitedQueryRelations<'a,
}
// preserve old columns while composing with new ones
let columns = &columns.clone().with(columns.and_then(new_columns));

Ok(RelationWithColumns::new(
Arc::new(relation),
columns.clone(),
Expand Down

0 comments on commit 82c0690

Please sign in to comment.