diff --git a/core/translate/mod.rs b/core/translate/mod.rs index 80b914379..8b47760ce 100644 --- a/core/translate/mod.rs +++ b/core/translate/mod.rs @@ -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, diff --git a/core/translate/planner.rs b/core/translate/planner.rs index ee99b5c53..cd1850812 100644 --- a/core/translate/planner.rs +++ b/core/translate/planner.rs @@ -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, diff --git a/core/translate/select.rs b/core/translate/select.rs index ae1079bef..877de7ac9 100644 --- a/core/translate/select.rs +++ b/core/translate/select.rs @@ -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)?; diff --git a/core/translate/update.rs b/core/translate/update.rs index 526d7da1b..6f8df6cc3 100644 --- a/core/translate/update.rs +++ b/core/translate/update.rs @@ -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::Result { 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() {