Err, don't panic, on unbound variable (#518) (#590) r=emily

* Pre: switch a 'panic' to an 'unreachable'.
* Make candidate_type_column fallible. (#518)
This commit is contained in:
Richard Newman 2018-03-15 11:39:24 -07:00 committed by GitHub
parent 994a3e65e2
commit 16a66517e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 11 deletions

View file

@ -371,12 +371,15 @@ fn candidate_column(cc: &ConjoiningClauses, var: &Variable) -> Result<(ColumnOrE
}) })
} }
fn candidate_type_column(cc: &ConjoiningClauses, var: &Variable) -> (ColumnOrExpression, Name) { fn candidate_type_column(cc: &ConjoiningClauses, var: &Variable) -> Result<(ColumnOrExpression, Name)> {
let extracted_alias = cc.extracted_types cc.extracted_types
.get(var) .get(var)
.expect("Every variable has a known type or an extracted type"); .cloned()
.map(|alias| {
let type_name = VariableColumn::VariableTypeTag(var.clone()).column_name(); let type_name = VariableColumn::VariableTypeTag(var.clone()).column_name();
(ColumnOrExpression::Column(extracted_alias.clone()), type_name) (ColumnOrExpression::Column(alias), type_name)
})
.ok_or_else(|| ErrorKind::UnboundVariable(var.name()).into())
} }
/// Return the projected column -- that is, a value or SQL column and an associated name -- for a /// Return the projected column -- that is, a value or SQL column and an associated name -- for a
@ -659,7 +662,7 @@ fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
i += 2; // We used two SQL columns. i += 2; // We used two SQL columns.
// Also project the type from the SQL query. // Also project the type from the SQL query.
let (type_column, type_name) = candidate_type_column(&query.cc, &var); let (type_column, type_name) = candidate_type_column(&query.cc, &var)?;
inner_projection.push(ProjectedColumn(type_column, type_name.clone())); inner_projection.push(ProjectedColumn(type_column, type_name.clone()));
outer_projection.push(Either::Left(type_name)); outer_projection.push(Either::Left(type_name));
} }
@ -694,7 +697,7 @@ fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
inner_projection.push(projected_column); inner_projection.push(projected_column);
if query.cc.known_type_set(&simple.var).unique_type_tag().is_none() { if query.cc.known_type_set(&simple.var).unique_type_tag().is_none() {
// Also project the type from the SQL query. // Also project the type from the SQL query.
let (type_column, type_name) = candidate_type_column(&query.cc, &simple.var); let (type_column, type_name) = candidate_type_column(&query.cc, &simple.var)?;
inner_projection.push(ProjectedColumn(type_column, type_name.clone())); inner_projection.push(ProjectedColumn(type_column, type_name.clone()));
} }
} }
@ -755,7 +758,7 @@ fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
// Single type implies single type tag, and is cheaper, so we check that first. // Single type implies single type tag, and is cheaper, so we check that first.
let types = query.cc.known_type_set(&var); let types = query.cc.known_type_set(&var);
if !types.has_unique_type_tag() { if !types.has_unique_type_tag() {
let (type_column, type_name) = candidate_type_column(&query.cc, &var); let (type_column, type_name) = candidate_type_column(&query.cc, &var)?;
if !already_inner { if !already_inner {
inner_projection.push(ProjectedColumn(type_column, type_name.clone())); inner_projection.push(ProjectedColumn(type_column, type_name.clone()));
} }
@ -836,7 +839,7 @@ fn project_elements<'a, I: IntoIterator<Item = &'a Element>>(
if type_set.unique_type_tag().is_none() { if type_set.unique_type_tag().is_none() {
// Also project the type from the SQL query. // Also project the type from the SQL query.
let (type_column, type_name) = candidate_type_column(&query.cc, &var); let (type_column, type_name) = candidate_type_column(&query.cc, &var)?;
inner_projection.push(ProjectedColumn(type_column, type_name.clone())); inner_projection.push(ProjectedColumn(type_column, type_name.clone()));
} }
} }

View file

@ -988,10 +988,11 @@ impl OrJoin {
let m = self.collect_mentioned_variables(); let m = self.collect_mentioned_variables();
self.mentioned_vars = Some(m); self.mentioned_vars = Some(m);
} }
if let Some(ref mentioned) = self.mentioned_vars { if let Some(ref mentioned) = self.mentioned_vars {
mentioned mentioned
} else { } else {
panic!() unreachable!()
} }
} }
} }