diff --git a/src/ts_generator/sql_parser/translate_delete.rs b/src/ts_generator/sql_parser/translate_delete.rs index 98ea2a42..8bd98970 100644 --- a/src/ts_generator/sql_parser/translate_delete.rs +++ b/src/ts_generator/sql_parser/translate_delete.rs @@ -2,18 +2,19 @@ use crate::core::connection::DBConn; use crate::ts_generator::errors::TsGeneratorError; use crate::ts_generator::sql_parser::expressions::translate_expr::translate_expr; use crate::ts_generator::types::ts_query::TsQuery; -use sqlparser::ast::Expr; +use sqlparser::ast::{Expr, TableWithJoins}; pub async fn translate_delete( ts_query: &mut TsQuery, where_conditions: &Expr, // WHERE conditions of the delete statement table_name: &str, + table_with_joins: &Option>, // Includes FROM and USING tables db_conn: &DBConn, ) -> Result<(), TsGeneratorError> { translate_expr( where_conditions, &Some(table_name), - &None, + table_with_joins, None, ts_query, db_conn, diff --git a/src/ts_generator/sql_parser/translate_stmt.rs b/src/ts_generator/sql_parser/translate_stmt.rs index b9d29f27..f2887e9a 100644 --- a/src/ts_generator/sql_parser/translate_stmt.rs +++ b/src/ts_generator/sql_parser/translate_stmt.rs @@ -52,7 +52,15 @@ pub async fn translate_stmt( let table_name = get_default_table(from); let table_name_str = table_name.as_str(); let selection = delete.selection.to_owned().unwrap(); - translate_delete(ts_query, &selection, table_name_str, db_conn).await?; + + // Build a combined Vec that includes both FROM and USING tables + let mut all_tables = from.to_vec(); + if let Some(using_tables) = &delete.using { + all_tables.extend(using_tables.clone()); + } + let table_with_joins = if all_tables.is_empty() { None } else { Some(all_tables) }; + + translate_delete(ts_query, &selection, table_name_str, &table_with_joins, db_conn).await?; // Handle RETURNING clause if present if delete.returning.is_some() { diff --git a/tests/mysql_delete_query_parameters.rs b/tests/mysql_delete_query_parameters.rs index 25c45a6a..bd6dde2c 100644 --- a/tests/mysql_delete_query_parameters.rs +++ b/tests/mysql_delete_query_parameters.rs @@ -56,12 +56,148 @@ r#" export type SomeDeleteQueryParams = [number, number]; export interface ISomeDeleteQueryResult { - + } export interface ISomeDeleteQueryQuery { params: SomeDeleteQueryParams; result: ISomeDeleteQueryResult; } +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_with_join_using_aliases, TestConfig::new("mysql", true, None, None), + +//// TS query //// +r#" +const deleteInventory = sql` +DELETE inv FROM inventory inv +INNER JOIN characters c ON inv.character_id = c.id +WHERE c.id = ? + AND inv.id = ?; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteInventoryParams = [number, number]; + +export interface IDeleteInventoryResult { + +} + +export interface IDeleteInventoryQuery { + params: DeleteInventoryParams; + result: IDeleteInventoryResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_with_multiple_joins, TestConfig::new("mysql", true, None, None), + +//// TS query //// +r#" +const deleteItems = sql` +DELETE i FROM items i +INNER JOIN inventory inv ON i.inventory_id = inv.id +INNER JOIN characters c ON inv.character_id = c.id +WHERE c.id = ? + AND i.rarity = ?; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteItemsParams = [number, string | null]; + +export interface IDeleteItemsResult { + +} + +export interface IDeleteItemsQuery { + params: DeleteItemsParams; + result: IDeleteItemsResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_with_left_join, TestConfig::new("mysql", true, None, None), + +//// TS query //// +r#" +const deleteByCharacter = sql` +DELETE inv FROM inventory inv +LEFT JOIN characters c ON inv.character_id = c.id +WHERE c.id = ? + AND inv.quantity = 0; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteByCharacterParams = [number]; + +export interface IDeleteByCharacterResult { + +} + +export interface IDeleteByCharacterQuery { + params: DeleteByCharacterParams; + result: IDeleteByCharacterResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_with_comparison_and_join, TestConfig::new("mysql", true, None, None), + +//// TS query //// +r#" +const deleteByQuantity = sql` +DELETE inv FROM inventory inv +INNER JOIN items i ON i.inventory_id = inv.id +WHERE i.rarity = ? + AND inv.quantity < ?; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteByQuantityParams = [string | null, number | null]; + +export interface IDeleteByQuantityResult { + +} + +export interface IDeleteByQuantityQuery { + params: DeleteByQuantityParams; + result: IDeleteByQuantityResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_with_or_conditions_and_join, TestConfig::new("mysql", true, None, None), + +//// TS query //// +r#" +const deleteConditional = sql` +DELETE inv FROM inventory inv +INNER JOIN characters c ON inv.character_id = c.id +WHERE (c.id = ? OR c.name = ?) + AND inv.quantity = 0; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteConditionalParams = [number, string]; + +export interface IDeleteConditionalResult { + +} + +export interface IDeleteConditionalQuery { + params: DeleteConditionalParams; + result: IDeleteConditionalResult; +} "#); } diff --git a/tests/postgres_delete_query_parameters.rs b/tests/postgres_delete_query_parameters.rs index 63cc182f..292cf809 100644 --- a/tests/postgres_delete_query_parameters.rs +++ b/tests/postgres_delete_query_parameters.rs @@ -56,12 +56,152 @@ r#" export type SomeDeleteQueryParams = [number, number]; export interface ISomeDeleteQueryResult { - + } export interface ISomeDeleteQueryQuery { params: SomeDeleteQueryParams; result: ISomeDeleteQueryResult; } +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_using_with_aliases, TestConfig::new("postgres", true, None, None), + +//// TS query //// +r#" +const deleteInventory = sql` +DELETE FROM inventory inv +USING characters c +WHERE inv.character_id = c.id + AND c.id = $1 + AND inv.id = $2; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteInventoryParams = [number, number]; + +export interface IDeleteInventoryResult { + +} + +export interface IDeleteInventoryQuery { + params: DeleteInventoryParams; + result: IDeleteInventoryResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_using_with_multiple_tables, TestConfig::new("postgres", true, None, None), + +//// TS query //// +r#" +const deleteItems = sql` +DELETE FROM items i +USING inventory inv, characters c +WHERE i.inventory_id = inv.id + AND inv.character_id = c.id + AND c.id = $1 + AND i.rarity = $2; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteItemsParams = [number, string | null]; + +export interface IDeleteItemsResult { + +} + +export interface IDeleteItemsQuery { + params: DeleteItemsParams; + result: IDeleteItemsResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_using_with_comparison, TestConfig::new("postgres", true, None, None), + +//// TS query //// +r#" +const deleteOldInventory = sql` +DELETE FROM inventory inv +USING characters c +WHERE inv.character_id = c.id + AND c.id = $1 + AND inv.quantity > $2; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteOldInventoryParams = [number, number | null]; + +export interface IDeleteOldInventoryResult { + +} + +export interface IDeleteOldInventoryQuery { + params: DeleteOldInventoryParams; + result: IDeleteOldInventoryResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_using_with_in_clause, TestConfig::new("postgres", true, None, None), + +//// TS query //// +r#" +const deleteByRarity = sql` +DELETE FROM inventory inv +USING items i +WHERE i.inventory_id = inv.id + AND i.rarity = $1; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteByRarityParams = [string | null]; + +export interface IDeleteByRarityResult { + +} + +export interface IDeleteByRarityQuery { + params: DeleteByRarityParams; + result: IDeleteByRarityResult; +} +"#); + + #[rustfmt::skip] +run_test!(should_handle_delete_using_with_or_conditions, TestConfig::new("postgres", true, None, None), + +//// TS query //// +r#" +const deleteConditional = sql` +DELETE FROM inventory inv +USING characters c +WHERE inv.character_id = c.id + AND (c.id = $1 OR c.name = $2) + AND inv.quantity = 0; +` +"#, + +//// Generated TS interfaces //// +r#" +export type DeleteConditionalParams = [number, string]; + +export interface IDeleteConditionalResult { + +} + +export interface IDeleteConditionalQuery { + params: DeleteConditionalParams; + result: IDeleteConditionalResult; +} "#); } diff --git a/tests/sample/sample.queries.ts b/tests/sample/sample.queries.ts new file mode 100644 index 00000000..f29c73b5 --- /dev/null +++ b/tests/sample/sample.queries.ts @@ -0,0 +1,44 @@ +export type SampleSelectQueryParams = [number]; + +export interface ISampleSelectQueryResult { + name: string; + some_id: number; +} + +export interface ISampleSelectQueryQuery { + params: SampleSelectQueryParams; + result: ISampleSelectQueryResult; +} + +export type SampleInsertQueryParams = [string]; + +export interface ISampleInsertQueryResult { + +} + +export interface ISampleInsertQueryQuery { + params: SampleInsertQueryParams; + result: ISampleInsertQueryResult; +} + +export type SampleUpdateQueryParams = [string, number]; + +export interface ISampleUpdateQueryResult { + +} + +export interface ISampleUpdateQueryQuery { + params: SampleUpdateQueryParams; + result: ISampleUpdateQueryResult; +} + +export type SampleDeleteQueryParams = [number]; + +export interface ISampleDeleteQueryResult { + +} + +export interface ISampleDeleteQueryQuery { + params: SampleDeleteQueryParams; + result: ISampleDeleteQueryResult; +}