diff --git a/partiql-ast-passes/src/name_resolver.rs b/partiql-ast-passes/src/name_resolver.rs index 3cacbf4c..57a00de7 100644 --- a/partiql-ast-passes/src/name_resolver.rs +++ b/partiql-ast-passes/src/name_resolver.rs @@ -2,7 +2,7 @@ use crate::error::{AstTransformError, AstTransformationError}; use fnv::FnvBuildHasher; use indexmap::{IndexMap, IndexSet}; use partiql_ast::ast; -use partiql_ast::ast::{GroupByExpr, GroupKey}; +use partiql_ast::ast::{GroupByExpr, GroupKey, SymbolPrimitive}; use partiql_ast::visit::{Traverse, Visit, Visitor}; use partiql_catalog::Catalog; use std::sync::atomic::{AtomicU32, Ordering}; @@ -209,6 +209,19 @@ impl<'c> NameResolver<'c> { fn push_consume_name(&mut self, name: NameRef) { self.keyref_stack.last_mut().unwrap().consume.insert(name); } + + #[inline] + fn catalog_resolvable(&mut self, name: &SymbolPrimitive) -> bool { + // TODO fix the name look up based on case sensitivity: + // https://github.com/partiql/partiql-lang-rust/issues/426 + dbg!(self.catalog); + + if let Some(_) = self.catalog.resolve_type(name.value.as_str()) { + true + } else { + false + } + } } impl<'ast, 'c> Visitor<'ast> for NameResolver<'c> { @@ -358,19 +371,32 @@ impl<'ast, 'c> Visitor<'ast> for NameResolver<'c> { // in a From path, a prefix `@` means to look locally before globally Cf. specification section 10 let name = if is_from_path { match &var_ref.qualifier { - ast::ScopeQualifier::Unqualified => NameRef { - sym: var_ref.name.clone(), - lookup: vec![NameLookup::Global, NameLookup::Local], - }, + ast::ScopeQualifier::Unqualified => { + if self.catalog_resolvable(&var_ref.name) { + NameRef { + sym: var_ref.name.clone(), + lookup: vec![NameLookup::Global], + } + } else { + // self.errors.push(AstTransformError::IllegalState(format!( + // "No schema found for [{:?}] in the Catalog", + // &var_ref.name + // ))); + NameRef { + sym: var_ref.name.clone(), + lookup: vec![NameLookup::Global], + } + } + } ast::ScopeQualifier::Qualified => NameRef { sym: var_ref.name.clone(), - lookup: vec![NameLookup::Local, NameLookup::Global], + lookup: vec![NameLookup::Local], }, } } else { NameRef { sym: var_ref.name.clone(), - lookup: vec![NameLookup::Local, NameLookup::Global], + lookup: vec![NameLookup::Local], } }; diff --git a/partiql-logical-planner/Cargo.toml b/partiql-logical-planner/Cargo.toml index 36724e5b..83c0127b 100644 --- a/partiql-logical-planner/Cargo.toml +++ b/partiql-logical-planner/Cargo.toml @@ -43,3 +43,4 @@ thiserror = "1.0" [dev-dependencies] partiql-eval = { path = "../partiql-eval", version = "0.5.*" } +partiql-types = { path = "../partiql-types", version = "0.5.*"} diff --git a/partiql-logical-planner/src/lib.rs b/partiql-logical-planner/src/lib.rs index e1f58630..ad40540e 100644 --- a/partiql-logical-planner/src/lib.rs +++ b/partiql-logical-planner/src/lib.rs @@ -37,7 +37,9 @@ impl<'c> LogicalPlanner<'c> { mod tests { use assert_matches::assert_matches; use partiql_ast_passes::error::AstTransformationError; - use partiql_catalog::PartiqlCatalog; + use partiql_catalog::Catalog; + use partiql_catalog::{PartiqlCatalog, TypeEnvEntry}; + use partiql_types::any; use partiql_eval::env::basic::MapBindings; @@ -59,7 +61,8 @@ mod tests { fn lower( parsed: &Parsed, ) -> Result, AstTransformationError> { - let catalog = PartiqlCatalog::default(); + let mut catalog = PartiqlCatalog::default(); + let _oid = catalog.add_type_entry(TypeEnvEntry::new("customer", &[], any!())); let planner = LogicalPlanner::new(&catalog); planner.lower(parsed) } @@ -67,6 +70,7 @@ mod tests { #[track_caller] fn evaluate(logical: LogicalPlan, bindings: MapBindings) -> Value { let catalog = PartiqlCatalog::default(); + let mut planner = plan::EvaluatorPlanner::new(EvaluationMode::Permissive, &catalog); let mut plan = planner.compile(&logical).expect("Expect no plan error"); println!("{}", plan.to_dot_graph()); diff --git a/partiql-logical-planner/src/lower.rs b/partiql-logical-planner/src/lower.rs index e742465e..25f82890 100644 --- a/partiql-logical-planner/src/lower.rs +++ b/partiql-logical-planner/src/lower.rs @@ -418,8 +418,6 @@ impl<'a> AstToLogical<'a> { } } - // TODO in the presence of schema, error if the variable reference doesn't correspond to a data table - // assume global ValueExpr::VarRef(symprim_to_binding(&varref.name), VarRefType::Global) }