mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-26 04:24:21 +01:00
Merge 'translate: return parse errors for unsupported features instead of silently ignoring' from Jussi Saurio
Closes #1510 Closes #2505
This commit is contained in:
@@ -51,7 +51,7 @@ use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use tracing::{instrument, Level};
|
||||
use transaction::{translate_tx_begin, translate_tx_commit};
|
||||
use turso_sqlite3_parser::ast::{self, Delete, Insert};
|
||||
use turso_sqlite3_parser::ast::{self, Delete, Indexed, Insert};
|
||||
use update::translate_update;
|
||||
|
||||
#[instrument(skip_all, level = Level::DEBUG)]
|
||||
@@ -156,16 +156,21 @@ pub fn translate_inner(
|
||||
idx_name,
|
||||
tbl_name,
|
||||
columns,
|
||||
..
|
||||
} => translate_create_index(
|
||||
(unique, if_not_exists),
|
||||
idx_name.name.as_str(),
|
||||
tbl_name.as_str(),
|
||||
&columns,
|
||||
schema,
|
||||
syms,
|
||||
program,
|
||||
)?,
|
||||
where_clause,
|
||||
} => {
|
||||
if where_clause.is_some() {
|
||||
bail_parse_error!("Partial indexes are not supported");
|
||||
}
|
||||
translate_create_index(
|
||||
(unique, if_not_exists),
|
||||
idx_name.name.as_str(),
|
||||
tbl_name.as_str(),
|
||||
&columns,
|
||||
schema,
|
||||
syms,
|
||||
program,
|
||||
)?
|
||||
}
|
||||
ast::Stmt::CreateTable {
|
||||
temporary,
|
||||
if_not_exists,
|
||||
@@ -191,8 +196,19 @@ pub fn translate_inner(
|
||||
where_clause,
|
||||
limit,
|
||||
returning,
|
||||
..
|
||||
indexed,
|
||||
order_by,
|
||||
with,
|
||||
} = *delete;
|
||||
if with.is_some() {
|
||||
bail_parse_error!("WITH clause is not supported in DELETE");
|
||||
}
|
||||
if indexed.is_some_and(|i| matches!(i, Indexed::IndexedBy(_))) {
|
||||
bail_parse_error!("INDEXED BY clause is not supported in DELETE");
|
||||
}
|
||||
if order_by.is_some() {
|
||||
bail_parse_error!("ORDER BY clause is not supported in DELETE");
|
||||
}
|
||||
translate_delete(
|
||||
schema,
|
||||
&tbl_name,
|
||||
|
||||
@@ -46,8 +46,19 @@ pub fn resolve_aggregates(
|
||||
name,
|
||||
args,
|
||||
distinctness,
|
||||
..
|
||||
filter_over,
|
||||
order_by,
|
||||
} => {
|
||||
if filter_over.is_some() {
|
||||
crate::bail_parse_error!(
|
||||
"FILTER clause is not supported yet in aggregate functions"
|
||||
);
|
||||
}
|
||||
if order_by.is_some() {
|
||||
crate::bail_parse_error!(
|
||||
"ORDER BY clause is not supported yet in aggregate functions"
|
||||
);
|
||||
}
|
||||
let args_count = if let Some(args) = &args {
|
||||
args.len()
|
||||
} else {
|
||||
@@ -84,7 +95,12 @@ pub fn resolve_aggregates(
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::FunctionCallStar { name, .. } => {
|
||||
Expr::FunctionCallStar { name, filter_over } => {
|
||||
if filter_over.is_some() {
|
||||
crate::bail_parse_error!(
|
||||
"FILTER clause is not supported yet in aggregate functions"
|
||||
);
|
||||
}
|
||||
if let Ok(Func::Agg(f)) = Func::resolve_function(name.as_str(), 0) {
|
||||
aggs.push(Aggregate {
|
||||
func: f,
|
||||
|
||||
@@ -194,6 +194,7 @@ fn prepare_one_select_plan(
|
||||
where_clause,
|
||||
group_by,
|
||||
distinctness,
|
||||
window_clause,
|
||||
..
|
||||
} = *select_inner;
|
||||
if !schema.indexes_enabled() && distinctness.is_some() {
|
||||
@@ -201,6 +202,9 @@ fn prepare_one_select_plan(
|
||||
"SELECT with DISTINCT is not allowed without indexes enabled"
|
||||
);
|
||||
}
|
||||
if window_clause.is_some() {
|
||||
crate::bail_parse_error!("WINDOW clause is not supported yet");
|
||||
}
|
||||
let col_count = columns.len();
|
||||
if col_count == 0 {
|
||||
crate::bail_parse_error!("SELECT without columns is not allowed");
|
||||
@@ -342,9 +346,17 @@ fn prepare_one_select_plan(
|
||||
name,
|
||||
distinctness,
|
||||
args,
|
||||
filter_over: _,
|
||||
order_by: _,
|
||||
filter_over,
|
||||
order_by,
|
||||
} => {
|
||||
if filter_over.is_some() {
|
||||
crate::bail_parse_error!(
|
||||
"FILTER clause is not supported yet in aggregate functions"
|
||||
);
|
||||
}
|
||||
if order_by.is_some() {
|
||||
crate::bail_parse_error!("ORDER BY clause is not supported yet in aggregate functions");
|
||||
}
|
||||
let args_count = if let Some(args) = &args {
|
||||
args.len()
|
||||
} else {
|
||||
@@ -465,47 +477,53 @@ fn prepare_one_select_plan(
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::Expr::FunctionCallStar {
|
||||
name,
|
||||
filter_over: _,
|
||||
} => match Func::resolve_function(name.as_str(), 0) {
|
||||
Ok(Func::Agg(f)) => {
|
||||
let agg = Aggregate {
|
||||
func: f,
|
||||
args: vec![ast::Expr::Literal(ast::Literal::Numeric(
|
||||
"1".to_string(),
|
||||
))],
|
||||
original_expr: expr.clone(),
|
||||
distinctness: Distinctness::NonDistinct,
|
||||
};
|
||||
aggregate_expressions.push(agg.clone());
|
||||
plan.result_columns.push(ResultSetColumn {
|
||||
alias: maybe_alias.as_ref().map(|alias| match alias {
|
||||
ast::As::Elided(alias) => alias.as_str().to_string(),
|
||||
ast::As::As(alias) => alias.as_str().to_string(),
|
||||
}),
|
||||
expr: expr.clone(),
|
||||
contains_aggregates: true,
|
||||
});
|
||||
}
|
||||
Ok(_) => {
|
||||
ast::Expr::FunctionCallStar { name, filter_over } => {
|
||||
if filter_over.is_some() {
|
||||
crate::bail_parse_error!(
|
||||
"Invalid aggregate function: {}",
|
||||
name.as_str()
|
||||
"FILTER clause is not supported yet in aggregate functions"
|
||||
);
|
||||
}
|
||||
Err(e) => match e {
|
||||
crate::LimboError::ParseError(e) => {
|
||||
crate::bail_parse_error!("{}", e);
|
||||
match Func::resolve_function(name.as_str(), 0) {
|
||||
Ok(Func::Agg(f)) => {
|
||||
let agg = Aggregate {
|
||||
func: f,
|
||||
args: vec![ast::Expr::Literal(ast::Literal::Numeric(
|
||||
"1".to_string(),
|
||||
))],
|
||||
original_expr: expr.clone(),
|
||||
distinctness: Distinctness::NonDistinct,
|
||||
};
|
||||
aggregate_expressions.push(agg.clone());
|
||||
plan.result_columns.push(ResultSetColumn {
|
||||
alias: maybe_alias.as_ref().map(|alias| match alias {
|
||||
ast::As::Elided(alias) => {
|
||||
alias.as_str().to_string()
|
||||
}
|
||||
ast::As::As(alias) => alias.as_str().to_string(),
|
||||
}),
|
||||
expr: expr.clone(),
|
||||
contains_aggregates: true,
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
Ok(_) => {
|
||||
crate::bail_parse_error!(
|
||||
"Invalid aggregate function: {}",
|
||||
name.as_str()
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
Err(e) => match e {
|
||||
crate::LimboError::ParseError(e) => {
|
||||
crate::bail_parse_error!("{}", e);
|
||||
}
|
||||
_ => {
|
||||
crate::bail_parse_error!(
|
||||
"Invalid aggregate function: {}",
|
||||
name.as_str()
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
expr => {
|
||||
let contains_aggregates =
|
||||
resolve_aggregates(schema, expr, &mut aggregate_expressions)?;
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
vdbe::builder::{ProgramBuilder, ProgramBuilderOpts},
|
||||
SymbolTable,
|
||||
};
|
||||
use turso_sqlite3_parser::ast::{Expr, SortOrder, Update};
|
||||
use turso_sqlite3_parser::ast::{Expr, Indexed, SortOrder, Update};
|
||||
|
||||
use super::emitter::emit_program;
|
||||
use super::expr::process_returning_clause;
|
||||
@@ -100,10 +100,17 @@ pub fn prepare_update_plan(
|
||||
connection: &Arc<crate::Connection>,
|
||||
) -> crate::Result<Plan> {
|
||||
if body.with.is_some() {
|
||||
bail_parse_error!("WITH clause is not supported");
|
||||
bail_parse_error!("WITH clause is not supported in UPDATE");
|
||||
}
|
||||
if body.or_conflict.is_some() {
|
||||
bail_parse_error!("ON CONFLICT clause is not supported");
|
||||
bail_parse_error!("ON CONFLICT clause is not supported in UPDATE");
|
||||
}
|
||||
if body
|
||||
.indexed
|
||||
.as_ref()
|
||||
.is_some_and(|i| matches!(i, Indexed::IndexedBy(_)))
|
||||
{
|
||||
bail_parse_error!("INDEXED BY clause is not supported in UPDATE");
|
||||
}
|
||||
let table_name = &body.tbl_name.name;
|
||||
if schema.table_has_indexes(&table_name.to_string()) && !schema.indexes_enabled() {
|
||||
|
||||
Reference in New Issue
Block a user