Skip to content

Commit

Permalink
Avoid panicking in certain unsupported SQL paths (#121)
Browse files Browse the repository at this point in the history
Prior to this commit, it was possible for certain CLI `spacetime sql` invocations
to crash SpacetimeDB by including unsupported features.
This was due to the SQL parser using the `todo!` macro,
where it should have returned a `PlanError::Unsupported` error.

With this commit, several uses of `todo!` are rewritten
to instead return errors,
which are translated appropriately into 400 responses,
rather than crashing SpacetimeDB.
  • Loading branch information
gefjon authored and cloutiertyler committed Aug 1, 2023
1 parent b87ea2b commit 407aea3
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 17 deletions.
24 changes: 15 additions & 9 deletions crates/core/src/sql/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,9 @@ fn compile_expr_value(table: &From, field: Option<&ProductTypeElement>, of: SqlE
fn compile_expr_field(table: &From, field: Option<&ProductTypeElement>, of: SqlExpr) -> Result<FieldExpr, PlanError> {
match compile_expr_value(table, field, of)? {
ColumnOp::Field(field) => Ok(field),
x => todo!("Complex expression {x} on insert..."),
x => Err(PlanError::Unsupported {
feature: format!("Complex expression {x} on insert..."),
}),
}
}

Expand Down Expand Up @@ -475,8 +477,12 @@ fn compile_from(db: &RelationalDB, tx: &MutTxId, from: &[TableWithJoins]) -> Res
(ColumnOp::Field(FieldExpr::Name(lhs)), ColumnOp::Field(FieldExpr::Name(rhs))) => {
(lhs, rhs)
}
_ => {
todo!()
(lhs, rhs) => {
return Err(PlanError::Unsupported {
feature: format!(
"Can't compare non-field expressions {lhs} and {rhs} in JOIN clause"
),
});
}
};

Expand Down Expand Up @@ -523,14 +529,14 @@ fn compile_select_item(from: &From, select_item: SelectItem) -> Result<Column, P
let value = compile_expr_value(from, None, expr)?;
match value {
ColumnOp::Field(value) => match value {
FieldExpr::Name(_) => {
unreachable!("Should not be an identifier in Expr::Value")
}
FieldExpr::Name(_) => Err(PlanError::Unsupported {
feature: "Should not be an identifier in Expr::Value".to_string(),
}),
FieldExpr::Value(x) => Ok(Column::UnnamedExpr(Expr::Value(x))),
},
x => {
unreachable!("Should not be an {} in Expr::Value", x)
}
x => Err(PlanError::Unsupported {
feature: format!("Should not be an {x} in Expr::Value"),
}),
}
}
sqlparser::ast::Expr::Nested(x) => compile_select_item(from, SelectItem::UnnamedExpr(*x)),
Expand Down
13 changes: 5 additions & 8 deletions crates/core/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,21 @@ impl<'db, 'tx> DbProgram<'db, 'tx> {

fn _execute_insert(&mut self, table: &Table, rows: Vec<ProductValue>) -> Result<Code, ErrorVm> {
match table {
Table::MemTable(_) => {
todo!("How deal with mutating values?")
}
// TODO: How do we deal with mutating values?
Table::MemTable(_) => Err(ErrorVm::Other(anyhow::anyhow!("How deal with mutating values?"))),
Table::DbTable(x) => {
for row in rows {
self.db.insert(self.tx, x.table_id, row)?;
}
Ok(Code::Pass)
}
}

Ok(Code::Pass)
}

fn _execute_delete(&mut self, table: &Table, rows: Vec<ProductValue>) -> Result<Code, ErrorVm> {
match table {
Table::MemTable(_) => {
todo!("How deal with mutating values?")
}
// TODO: How do we deal with mutating values?
Table::MemTable(_) => Err(ErrorVm::Other(anyhow::anyhow!("How deal with mutating values?"))),
Table::DbTable(t) => {
let count = self.db.delete_by_rel(self.tx, t.table_id, rows)?;
Ok(Code::Value(count.unwrap_or_default().into()))
Expand Down

0 comments on commit 407aea3

Please sign in to comment.