diff --git a/Cargo.lock b/Cargo.lock index 11cd2ead7..bd0d38c18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -604,7 +604,7 @@ dependencies = [ "axum", "insta", "ndc-postgres", - "ndc-test", + "ndc-test 0.1.0 (git+https://github.com/hasura/ndc-spec.git?tag=v0.1.0-rc.13)", "openapi-generator", "schemars", "serde_json", @@ -1475,6 +1475,23 @@ dependencies = [ "url", ] +[[package]] +name = "ndc-client" +version = "0.1.0" +source = "git+http://github.com/hasura/ndc-spec.git?rev=545e0b894a266c9768afd0ea0dadf09a50e15825#545e0b894a266c9768afd0ea0dadf09a50e15825" +dependencies = [ + "async-trait", + "indexmap 2.1.0", + "opentelemetry", + "reqwest", + "schemars", + "serde", + "serde_derive", + "serde_json", + "serde_with 2.3.3", + "url", +] + [[package]] name = "ndc-postgres" version = "0.1.0" @@ -1485,9 +1502,9 @@ dependencies = [ "env_logger", "hyper", "insta", - "ndc-client", + "ndc-client 0.1.0 (git+https://github.com/hasura/ndc-spec.git?tag=v0.1.0-rc.13)", "ndc-sdk", - "ndc-test", + "ndc-test 0.1.0 (git+https://github.com/hasura/ndc-spec.git?tag=v0.1.0-rc.13)", "percent-encoding", "prometheus", "query-engine-execution", @@ -1510,7 +1527,6 @@ dependencies = [ [[package]] name = "ndc-sdk" version = "0.1.0" -source = "git+https://github.com/hasura/ndc-hub.git?rev=3b6c480#3b6c48016473ce3369da76269a6e1c03f8af7b22" dependencies = [ "async-trait", "axum", @@ -1522,8 +1538,8 @@ dependencies = [ "http", "indexmap 2.1.0", "mime", - "ndc-client", - "ndc-test", + "ndc-client 0.1.0 (git+http://github.com/hasura/ndc-spec.git?rev=545e0b894a266c9768afd0ea0dadf09a50e15825)", + "ndc-test 0.1.0 (git+http://github.com/hasura/ndc-spec.git?rev=545e0b894a266c9768afd0ea0dadf09a50e15825)", "opentelemetry", "opentelemetry-http", "opentelemetry-otlp", @@ -1553,7 +1569,26 @@ dependencies = [ "clap", "colored", "indexmap 2.1.0", - "ndc-client", + "ndc-client 0.1.0 (git+https://github.com/hasura/ndc-spec.git?tag=v0.1.0-rc.13)", + "proptest", + "reqwest", + "semver", + "serde", + "serde_json", + "thiserror", + "tokio", +] + +[[package]] +name = "ndc-test" +version = "0.1.0" +source = "git+http://github.com/hasura/ndc-spec.git?rev=545e0b894a266c9768afd0ea0dadf09a50e15825#545e0b894a266c9768afd0ea0dadf09a50e15825" +dependencies = [ + "async-trait", + "clap", + "colored", + "indexmap 2.1.0", + "ndc-client 0.1.0 (git+http://github.com/hasura/ndc-spec.git?rev=545e0b894a266c9768afd0ea0dadf09a50e15825)", "proptest", "reqwest", "semver", @@ -3146,10 +3181,10 @@ dependencies = [ "env_logger", "hyper", "jsonschema", - "ndc-client", + "ndc-client 0.1.0 (git+https://github.com/hasura/ndc-spec.git?tag=v0.1.0-rc.13)", "ndc-postgres", "ndc-sdk", - "ndc-test", + "ndc-test 0.1.0 (git+https://github.com/hasura/ndc-spec.git?tag=v0.1.0-rc.13)", "reqwest", "schemars", "serde", diff --git a/crates/connectors/ndc-postgres/Cargo.toml b/crates/connectors/ndc-postgres/Cargo.toml index 251220753..15af04844 100644 --- a/crates/connectors/ndc-postgres/Cargo.toml +++ b/crates/connectors/ndc-postgres/Cargo.toml @@ -15,7 +15,7 @@ name = "ndc-postgres" path = "bin/main.rs" [dependencies] -ndc-sdk = { git = "https://github.com/hasura/ndc-hub.git", rev = "3b6c480" } +ndc-sdk = { path = "../../../../ndc-hub/rust-connector-sdk" } query-engine-execution = { path = "../../query-engine/execution" } query-engine-metadata = { path = "../../query-engine/metadata" } query-engine-sql = { path = "../../query-engine/sql" } diff --git a/crates/query-engine/translation/Cargo.toml b/crates/query-engine/translation/Cargo.toml index 42edf8571..64c8f4303 100644 --- a/crates/query-engine/translation/Cargo.toml +++ b/crates/query-engine/translation/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" license = "Apache-2.0" [dependencies] -ndc-sdk = { git = "https://github.com/hasura/ndc-hub.git", rev = "3b6c480" } +ndc-sdk = { path = "../../../../ndc-hub/rust-connector-sdk" } query-engine-metadata = { path = "../metadata" } query-engine-sql = { path = "../sql" } diff --git a/crates/query-engine/translation/src/translation/mutation/delete.rs b/crates/query-engine/translation/src/translation/mutation/delete.rs index 1763fd7b9..af35ca1ff 100644 --- a/crates/query-engine/translation/src/translation/mutation/delete.rs +++ b/crates/query-engine/translation/src/translation/mutation/delete.rs @@ -1,7 +1,10 @@ //! Auto-generate delete mutations and translate them into sql ast. use crate::translation::error::Error; +use crate::translation::helpers::{self, TableNameAndReference}; +use crate::translation::query::filtering; use crate::translation::query::values::translate_json_value; +use ndc_sdk::models; use query_engine_metadata::metadata; use query_engine_metadata::metadata::database; use query_engine_sql::sql::ast; @@ -68,17 +71,23 @@ pub fn generate_delete_by_unique( } /// Given the description of a delete mutation (ie, `DeleteMutation`), and the arguments, output the SQL AST. pub fn translate_delete( + env: &crate::translation::helpers::Env, state: &mut crate::translation::helpers::State, delete: &DeleteMutation, arguments: BTreeMap, ) -> Result { match delete { DeleteMutation::DeleteByKey { + collection_name, schema_name, table_name, by_column, .. } => { + let predicate_json = arguments + .get("%predicate") + .ok_or(Error::ArgumentNotFound("%predicate".to_string()))?; + let unique_key = arguments .get(&by_column.name) .ok_or(Error::ArgumentNotFound(by_column.name.clone()))?; @@ -92,6 +101,24 @@ pub fn translate_delete( let table_alias = state.make_table_alias(table_name.0.clone()); + let predicate: models::Expression = serde_json::from_value(predicate_json.clone()) + .map_err(|_| Error::ArgumentNotFound("%predicate".to_string()))?; + + let table_name_and_reference = TableNameAndReference { + name: collection_name.clone(), + reference: ast::TableReference::AliasedTable(table_alias.clone()), + }; + + let (predicate_expression, joins) = filtering::translate_expression( + env, + state, + &helpers::RootAndCurrentTables { + root_table: table_name_and_reference.clone(), + current_table: table_name_and_reference.clone(), + }, + &predicate, + )?; + let where_expr = ast::Expression::BinaryOperation { left: Box::new(ast::Expression::ColumnReference( ast::ColumnReference::TableColumn { @@ -108,66 +135,20 @@ pub fn translate_delete( alias: table_alias, }; + let where_ = if joins.is_empty() { + ast::Expression::And { + left: Box::new(where_expr), + right: Box::new(predicate_expression), + } + } else { + todo!() + }; + Ok(ast::Delete { from, - where_: ast::Where(where_expr), + where_: ast::Where(where_), returning: ast::Returning::ReturningStar, }) } } } - -#[cfg(test)] -mod tests { - use super::ast; - use super::DeleteMutation; - use crate::translation::helpers::State; - use crate::translation::mutation::delete::translate_delete; - use query_engine_metadata::metadata; - use query_engine_sql::sql::string; - use std::collections::BTreeMap; - - fn sample_delete() -> DeleteMutation { - DeleteMutation::DeleteByKey { - schema_name: ast::SchemaName("public".to_string()), - table_name: ast::TableName("User".to_string()), - collection_name: "User".to_string(), - by_column: metadata::ColumnInfo { - name: "user_id".to_string(), - description: None, - r#type: metadata::Type::ScalarType(metadata::ScalarType("int".to_string())), - nullable: metadata::Nullable::NonNullable, - has_default: metadata::HasDefault::NoDefault, - is_identity: metadata::IsIdentity::NotIdentity, - is_generated: metadata::IsGenerated::NotGenerated, - }, - description: "".to_string(), - } - } - - #[test] - fn delete_to_sql() { - let delete = sample_delete(); - - let mut state = State::new(); - - let mut arguments = BTreeMap::new(); - arguments.insert("user_id".to_string(), serde_json::Value::Number(100.into())); - - let result = translate_delete(&mut state, &delete, arguments).unwrap(); - - let mut sql = string::SQL::new(); - result.to_sql(&mut sql); - - let pretty = sqlformat::format( - &sql.sql, - &sqlformat::QueryParams::None, - sqlformat::FormatOptions::default(), - ); - - insta::with_settings!({snapshot_path => "../../../tests/snapshots"}, { - insta::assert_snapshot!(pretty); - - }); - } -} diff --git a/crates/query-engine/translation/src/translation/mutation/translate.rs b/crates/query-engine/translation/src/translation/mutation/translate.rs index ed5f6f847..96ed86f66 100644 --- a/crates/query-engine/translation/src/translation/mutation/translate.rs +++ b/crates/query-engine/translation/src/translation/mutation/translate.rs @@ -87,7 +87,7 @@ fn translate_mutation( ( return_collection, sql::ast::CTExpr::Delete(mutation::delete::translate_delete( - &mut state, &delete, arguments, + env, &mut state, &delete, arguments, )?), ) } diff --git a/crates/query-engine/translation/src/translation/query/mod.rs b/crates/query-engine/translation/src/translation/query/mod.rs index da93a756b..461c2ed7d 100644 --- a/crates/query-engine/translation/src/translation/query/mod.rs +++ b/crates/query-engine/translation/src/translation/query/mod.rs @@ -1,7 +1,7 @@ //! Translate an incoming `QueryRequest`. mod aggregates; -mod filtering; +pub mod filtering; pub mod native_queries; mod relationships; pub mod root; diff --git a/crates/tests/tests-common/Cargo.toml b/crates/tests/tests-common/Cargo.toml index a121e922b..9959b208a 100644 --- a/crates/tests/tests-common/Cargo.toml +++ b/crates/tests/tests-common/Cargo.toml @@ -11,7 +11,7 @@ path = "src/lib.rs" [dependencies] ndc-client = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.1.0-rc.13" } ndc-postgres = { path = "../../connectors/ndc-postgres" } -ndc-sdk = { git = "https://github.com/hasura/ndc-hub.git", rev = "3b6c480" } +ndc-sdk = { path = "../../../../ndc-hub/rust-connector-sdk" } ndc-test = { git = "https://github.com/hasura/ndc-spec.git", tag = "v0.1.0-rc.13" } axum = "0.6.20" diff --git a/crates/tests/tests-common/goldenfiles/mutations/delete_invoice_line.json b/crates/tests/tests-common/goldenfiles/mutations/delete_invoice_line.json index 8530cbf45..4cbb3f048 100644 --- a/crates/tests/tests-common/goldenfiles/mutations/delete_invoice_line.json +++ b/crates/tests/tests-common/goldenfiles/mutations/delete_invoice_line.json @@ -4,7 +4,23 @@ "type": "procedure", "name": "v1_delete_InvoiceLine_by_InvoiceLineId", "arguments": { - "InvoiceLineId": 90 + "InvoiceLineId": 91, + "%predicate": { + "type": "binary_comparison_operator", + "column": { + "type": "column", + "name": "InvoiceLineId", + "path": [] + }, + "operator": { + "type": "other", + "name": "_gt" + }, + "value": { + "type": "scalar", + "value": 340 + } + } }, "fields": { "invoice_line_id": {