use std::collections::HashMap;
use std::sync::Arc;
use crate::catalog::{Catalog, CatalogProvider, Column, HamelinType};
use crate::tree::ast::identifier::{Identifier, SimpleIdentifier};
use crate::tree::ast::query::Query;
use crate::tree::options::{TemplateParameterKind, TypeCheckOptions};
use crate::tree::typed_ast::query::TypedStatement;
use crate::{parse, type_check_with_options};
#[test]
fn templated_from_intersects_row_schemas() {
let mut catalog = Catalog::default();
catalog.0.insert(
Identifier::parse("db.t_alice").unwrap(),
vec![
Column::new("id", HamelinType::Int),
Column::new("x", HamelinType::String),
],
);
catalog.0.insert(
Identifier::parse("db.t_bob").unwrap(),
vec![Column::new("id", HamelinType::Int)],
);
let provider = Arc::new(CatalogProvider::try_from(catalog).unwrap());
let mut tmpl = HashMap::new();
tmpl.insert(
"which".to_string(),
TemplateParameterKind::IdentifierFragment(vec!["t_alice".to_string(), "t_bob".to_string()]),
);
let q = parse(r#"FROM db.${which}"#).into_result().expect("parse");
let typed: TypedStatement = type_check_with_options::<Query>(
Arc::new(q),
TypeCheckOptions::builder()
.provider(provider)
.maybe_template_parameters(Some(Arc::new(tmpl)))
.build(),
)
.into_result()
.expect("typecheck");
let schema = typed.schema();
assert!(schema.lookup(&SimpleIdentifier::new("id")).is_some());
assert!(schema.lookup(&SimpleIdentifier::new("x")).is_none());
}
#[test]
fn templated_join_requires_explicit_alias() {
let mut catalog = Catalog::default();
catalog.0.insert(
Identifier::parse("db.base").unwrap(),
vec![Column::new("id", HamelinType::Int)],
);
catalog.0.insert(
Identifier::parse("db.t_alice").unwrap(),
vec![Column::new("id", HamelinType::Int)],
);
let provider = Arc::new(CatalogProvider::try_from(catalog).unwrap());
let mut tmpl = HashMap::new();
tmpl.insert(
"which".to_string(),
TemplateParameterKind::IdentifierFragment(vec!["t_alice".to_string()]),
);
let q = parse(r#"FROM db.base | JOIN db.${which} ON true"#)
.into_result()
.expect("parse");
let err = type_check_with_options::<Query>(
Arc::new(q),
TypeCheckOptions::builder()
.provider(provider)
.maybe_template_parameters(Some(Arc::new(tmpl)))
.build(),
)
.into_result()
.expect_err("templated JOIN without alias should fail");
assert!(err.to_string().contains("require an explicit alias"));
}
#[test]
fn templated_match_requires_explicit_alias() {
let mut catalog = Catalog::default();
catalog.0.insert(
Identifier::parse("db.t_alice").unwrap(),
vec![Column::new("id", HamelinType::Int)],
);
let provider = Arc::new(CatalogProvider::try_from(catalog).unwrap());
let mut tmpl = HashMap::new();
tmpl.insert(
"which".to_string(),
TemplateParameterKind::IdentifierFragment(vec!["t_alice".to_string()]),
);
let q = parse(r#"MATCH db.${which}"#).into_result().expect("parse");
let err = type_check_with_options::<Query>(
Arc::new(q),
TypeCheckOptions::builder()
.provider(provider)
.maybe_template_parameters(Some(Arc::new(tmpl)))
.build(),
)
.into_result()
.expect_err("templated MATCH without alias should fail");
assert!(err.to_string().contains("require an explicit alias"));
}