diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/data_types/bytes.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/data_types/bytes.rs index 265a75763794..a4957d75e1ab 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/data_types/bytes.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/data_types/bytes.rs @@ -1,14 +1,6 @@ use query_engine_tests::*; -#[test_suite( - schema(common_nullable_types), - exclude( - Postgres("pg.js.wasm"), - Postgres("neon.js.wasm"), - Sqlite("libsql.js.wasm"), - Vitess("planetscale.js.wasm") - ) -)] +#[test_suite(schema(common_nullable_types))] mod bytes { use query_engine_tests::{run_query, EngineProtocol, Runner}; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bigint_filter.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bigint_filter.rs index 0ef65c7af43a..7234fcc253d0 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bigint_filter.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bigint_filter.rs @@ -143,11 +143,7 @@ mod bigint_filter { Ok(()) } - #[connector_test( - schema(setup::common_list_types), - exclude(Postgres("pg.js.wasm", "neon.js.wasm")), - capabilities(ScalarLists) - )] + #[connector_test(schema(setup::common_list_types), capabilities(ScalarLists))] async fn scalar_list_filters(runner: Runner) -> TestResult<()> { setup::test_data_list_common(&runner).await?; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bytes_filter.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bytes_filter.rs index a77bf6e765b2..bcb4a76c6158 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bytes_filter.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/bytes_filter.rs @@ -6,10 +6,7 @@ mod bytes_filter { use super::setup; use query_engine_tests::run_query; - #[connector_test( - schema(setup::common_types), - exclude(Sqlite("libsql.js.wasm"), Vitess("planetscale.js.wasm")) - )] + #[connector_test(schema(setup::common_types))] async fn basic_where(runner: Runner) -> TestResult<()> { setup::test_data_common_types(&runner).await?; @@ -31,11 +28,7 @@ mod bytes_filter { Ok(()) } - #[connector_test( - schema(setup::common_mixed_types), - exclude(Postgres("pg.js.wasm", "neon.js.wasm")), - capabilities(ScalarLists) - )] + #[connector_test(schema(setup::common_mixed_types), capabilities(ScalarLists))] async fn inclusion_filter(runner: Runner) -> TestResult<()> { setup::test_data_common_mixed_types(&runner).await?; @@ -57,11 +50,7 @@ mod bytes_filter { Ok(()) } - #[connector_test( - schema(setup::common_list_types), - exclude(Postgres("pg.js.wasm", "neon.js.wasm")), - capabilities(ScalarLists) - )] + #[connector_test(schema(setup::common_list_types), capabilities(ScalarLists))] async fn scalar_list_filters(runner: Runner) -> TestResult<()> { setup::test_data_list_common(&runner).await?; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/datetime_filter.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/datetime_filter.rs index 2753471bc635..327379bd4903 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/datetime_filter.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/datetime_filter.rs @@ -6,10 +6,7 @@ mod datetime_filter { use super::setup; use query_engine_tests::run_query; - #[connector_test( - schema(setup::common_types), - exclude(Sqlite("libsql.js.wasm"), Vitess("planetscale.js.wasm")) - )] + #[connector_test(schema(setup::common_types))] async fn basic_where(runner: Runner) -> TestResult<()> { setup::test_data_common_types(&runner).await?; @@ -31,10 +28,7 @@ mod datetime_filter { Ok(()) } - #[connector_test( - schema(setup::common_types), - exclude(Sqlite("libsql.js.wasm"), Vitess("planetscale.js.wasm")) - )] + #[connector_test(schema(setup::common_types))] async fn numeric_comparison_filters(runner: Runner) -> TestResult<()> { setup::test_data_common_types(&runner).await?; @@ -143,11 +137,7 @@ mod datetime_filter { Ok(()) } - #[connector_test( - schema(setup::common_list_types), - capabilities(ScalarLists), - exclude(Postgres("pg.js.wasm", "neon.js.wasm")) - )] + #[connector_test(schema(setup::common_list_types), capabilities(ScalarLists))] async fn scalar_list_filters(runner: Runner) -> TestResult<()> { setup::test_data_list_common(&runner).await?; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/float_filter.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/float_filter.rs index f40f73bbc180..580b7f31bc39 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/float_filter.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/float_filter.rs @@ -6,10 +6,7 @@ mod float_filter { use super::setup; use query_engine_tests::run_query; - #[connector_test( - schema(setup::common_types), - exclude(Sqlite("libsql.js.wasm"), Vitess("planetscale.js.wasm")) - )] + #[connector_test(schema(setup::common_types))] async fn basic_where(runner: Runner) -> TestResult<()> { setup::test_data_common_types(&runner).await?; @@ -31,10 +28,7 @@ mod float_filter { Ok(()) } - #[connector_test( - schema(setup::common_types), - exclude(Sqlite("libsql.js.wasm"), Vitess("planetscale.js.wasm")) - )] + #[connector_test(schema(setup::common_types))] async fn numeric_comparison_filters(runner: Runner) -> TestResult<()> { setup::test_data_common_types(&runner).await?; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/int_filter.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/int_filter.rs index cedbb81c3a1f..972539ec1f15 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/int_filter.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/int_filter.rs @@ -6,10 +6,7 @@ mod int_filter { use super::setup; use query_engine_tests::run_query; - #[connector_test( - schema(setup::common_types), - exclude(Sqlite("libsql.js.wasm"), Vitess("planetscale.js.wasm")) - )] + #[connector_test(schema(setup::common_types))] async fn basic_where(runner: Runner) -> TestResult<()> { setup::test_data_common_types(&runner).await?; @@ -31,10 +28,7 @@ mod int_filter { Ok(()) } - #[connector_test( - schema(setup::common_types), - exclude(Sqlite("libsql.js.wasm"), Vitess("planetscale.js.wasm")) - )] + #[connector_test(schema(setup::common_types))] async fn numeric_comparison_filters(runner: Runner) -> TestResult<()> { setup::test_data_common_types(&runner).await?; @@ -143,11 +137,7 @@ mod int_filter { Ok(()) } - #[connector_test( - schema(setup::common_list_types), - exclude(Postgres("pg.js.wasm", "neon.js.wasm")), - capabilities(ScalarLists) - )] + #[connector_test(schema(setup::common_list_types), capabilities(ScalarLists))] async fn scalar_list_filters(runner: Runner) -> TestResult<()> { setup::test_data_list_common(&runner).await?; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/string_filter.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/string_filter.rs index c62821ef4604..708f2d15e83e 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/string_filter.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/string_filter.rs @@ -435,11 +435,7 @@ mod string_filter { Ok(()) } - #[connector_test( - schema(setup::common_list_types), - exclude(Postgres("pg.js.wasm", "neon.js.wasm")), - capabilities(ScalarLists) - )] + #[connector_test(schema(setup::common_list_types), capabilities(ScalarLists))] async fn scalar_list_filters_sensitive(runner: Runner) -> TestResult<()> { setup::test_data_list_common(&runner).await?; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/list_filters.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/list_filters.rs index f34675ba3ff1..16b9a0ab0437 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/list_filters.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/list_filters.rs @@ -1,10 +1,6 @@ use query_engine_tests::*; -#[test_suite( - schema(common_list_types), - exclude(Postgres("pg.js.wasm", "neon.js.wasm")), - capabilities(ScalarLists) -)] +#[test_suite(schema(common_list_types), capabilities(ScalarLists))] mod lists { use indoc::indoc; use query_engine_tests::run_query; @@ -627,7 +623,7 @@ mod lists { } // Cockroachdb does not like the bytes empty array check in v21 but this will be fixed in 22. - #[connector_test(exclude(CockroachDB), exclude(Postgres("pg.js.wasm", "neon.js.wasm")))] + #[connector_test(exclude(CockroachDB))] async fn is_empty_bytes(runner: Runner) -> TestResult<()> { test_data(&runner).await?; diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bytes.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bytes.rs index 654463f491f7..a5f8b2d230d9 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bytes.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bytes.rs @@ -1,10 +1,6 @@ use query_engine_tests::*; -#[test_suite(exclude( - Postgres("pg.js.wasm", "neon.js.wasm"), - Sqlite("libsql.js.wasm"), - Vitess("planetscale.js.wasm") -))] +#[test_suite] mod bytes { use indoc::indoc; use query_engine_tests::run_query; @@ -81,16 +77,7 @@ mod bytes { Ok(()) } - #[connector_test( - schema(bytes_id), - exclude( - MySQL, - Vitess, - SqlServer, - Postgres("pg.js.wasm", "neon.js.wasm"), - Sqlite("libsql.js.wasm") - ) - )] + #[connector_test(schema(bytes_id), exclude(MySQL, Vitess, SqlServer,))] async fn byte_id_coercion(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(runner, r#" diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs index 2a83d17f6fb7..cb3cf9b366d6 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs @@ -191,11 +191,7 @@ mod postgres { } // "Other Postgres native types" should "work" - #[connector_test( - schema(schema_other_types), - only(Postgres), - exclude(CockroachDb, Postgres("pg.js.wasm", "neon.js.wasm")) - )] + #[connector_test(schema(schema_other_types), only(Postgres), exclude(CockroachDb,))] async fn native_other_types(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/base.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/base.rs index 2bd989573da8..9a5e74dd8547 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/base.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/base.rs @@ -28,7 +28,7 @@ mod basic_types { schema.to_owned() } - #[connector_test(exclude(Postgres("pg.js.wasm", "neon.js.wasm")))] + #[connector_test] async fn set_base(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, format!(r#"mutation {{ @@ -59,7 +59,7 @@ mod basic_types { // "Scalar lists" should "be behave like regular values for create and update operations" // Skipped for CockroachDB as enum array concatenation is not supported (https://github.com/cockroachdb/cockroach/issues/71388). - #[connector_test(exclude(CockroachDb, Postgres("pg.js.wasm", "neon.js.wasm")))] + #[connector_test(exclude(CockroachDb))] async fn behave_like_regular_val_for_create_and_update(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, format!(r#"mutation {{ @@ -158,7 +158,7 @@ mod basic_types { } // "A Create Mutation" should "create and return items with list values with shorthand notation" - #[connector_test(exclude(Postgres("pg.js.wasm", "neon.js.wasm")))] + #[connector_test] async fn create_mut_work_with_list_vals(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, format!(r#"mutation {{ diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/defaults.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/defaults.rs index c216b36ae458..39370e62c572 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/defaults.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/scalar_list/defaults.rs @@ -29,7 +29,7 @@ mod basic { schema.to_owned() } - #[connector_test(exclude(Postgres("pg.js.wasm", "neon.js.wasm")))] + #[connector_test] async fn basic_write(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { diff --git a/query-engine/driver-adapters/src/conversion/js_arg.rs b/query-engine/driver-adapters/src/conversion/js_arg.rs index c5b65e80882a..f306499dc516 100644 --- a/query-engine/driver-adapters/src/conversion/js_arg.rs +++ b/query-engine/driver-adapters/src/conversion/js_arg.rs @@ -1,8 +1,7 @@ use serde::Serialize; use serde_json::value::Value as JsonValue; -#[derive(Debug, PartialEq, Serialize)] -#[serde(untagged)] +#[derive(Debug, PartialEq)] pub enum JSArg { Value(serde_json::Value), Buffer(Vec), diff --git a/query-engine/driver-adapters/src/types.rs b/query-engine/driver-adapters/src/types.rs index bae6024ede3f..3f5a12b58f63 100644 --- a/query-engine/driver-adapters/src/types.rs +++ b/query-engine/driver-adapters/src/types.rs @@ -243,7 +243,6 @@ pub enum ColumnType { } #[cfg_attr(not(target_arch = "wasm32"), napi_derive::napi(object))] -#[cfg_attr(target_arch = "wasm32", derive(Serialize))] #[derive(Debug, Default)] pub struct Query { pub sql: String, diff --git a/query-engine/driver-adapters/src/wasm/adapter_method.rs b/query-engine/driver-adapters/src/wasm/adapter_method.rs index a66afeca4c5a..071bbbf3ebf9 100644 --- a/query-engine/driver-adapters/src/wasm/adapter_method.rs +++ b/query-engine/driver-adapters/src/wasm/adapter_method.rs @@ -9,17 +9,13 @@ use wasm_bindgen_futures::JsFuture; use super::error::into_quaint_error; use super::from_js::FromJsValue; +use super::to_js::ToJsValue; use crate::AdapterResult; -// `serialize_missing_as_null` is required to make sure that "empty" values (e.g., `None` and `()`) -// are serialized as `null` and not `undefined`. -// This is due to certain drivers (e.g., LibSQL) not supporting `undefined` values. -pub(crate) static SERIALIZER: Serializer = Serializer::new().serialize_missing_as_null(true); - #[derive(Clone)] pub(crate) struct AdapterMethod where - ArgType: Serialize, + ArgType: ToJsValue, ReturnType: FromJsValue, { fn_: JsFunction, @@ -30,7 +26,7 @@ where impl From for AdapterMethod where - T: Serialize, + T: ToJsValue, R: FromJsValue, { fn from(js_value: JsValue) -> Self { @@ -40,7 +36,7 @@ where impl From for AdapterMethod where - T: Serialize, + T: ToJsValue, R: FromJsValue, { fn from(js_fn: JsFunction) -> Self { @@ -54,7 +50,7 @@ where impl AdapterMethod where - T: Serialize, + T: ToJsValue, R: FromJsValue, { pub(crate) async fn call_as_async(&self, arg1: T) -> quaint::Result { @@ -82,14 +78,12 @@ where } async fn call_internal(&self, arg1: T) -> Result { - let arg1 = arg1 - .serialize(&SERIALIZER) - .map_err(|err| JsValue::from(JsError::from(&err)))?; + let arg1 = arg1.to_js_value()?; self.fn_.call1(&JsValue::null(), &arg1) } pub(crate) fn call_non_blocking(&self, arg: T) { - if let Ok(arg) = serde_wasm_bindgen::to_value(&arg) { + if let Ok(arg) = arg.to_js_value() { _ = self.fn_.call1(&JsValue::null(), &arg); } } @@ -97,7 +91,7 @@ where impl WasmDescribe for AdapterMethod where - ArgType: Serialize, + ArgType: ToJsValue, ReturnType: FromJsValue, { fn describe() { @@ -107,7 +101,7 @@ where impl FromWasmAbi for AdapterMethod where - ArgType: Serialize, + ArgType: ToJsValue, ReturnType: FromJsValue, { type Abi = ::Abi; diff --git a/query-engine/driver-adapters/src/wasm/conversion.rs b/query-engine/driver-adapters/src/wasm/conversion.rs new file mode 100644 index 000000000000..c41ff8a23107 --- /dev/null +++ b/query-engine/driver-adapters/src/wasm/conversion.rs @@ -0,0 +1,52 @@ +use crate::conversion::JSArg; + +use super::to_js::{serde_serialize, ToJsValue}; +use crate::types::Query; +use js_sys::{Array, JsString, Object, Reflect, Uint8Array}; +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends = Object)] + pub type Buffer; + + #[wasm_bindgen(static_method_of = Buffer)] + pub fn from(array: &Uint8Array) -> Buffer; +} + +impl ToJsValue for Query { + fn to_js_value(&self) -> Result { + let object = Object::new(); + let sql = self.sql.to_js_value()?; + Reflect::set(&object, &JsValue::from(JsString::from("sql")), &sql)?; + let args = Array::new(); + for arg in &self.args { + let value = arg.to_js_value()?; + args.push(&value); + } + Reflect::set(&object, &JsValue::from(JsString::from("args")), &args)?; + + Ok(JsValue::from(object)) + } +} + +impl ToJsValue for JSArg { + fn to_js_value(&self) -> Result { + match self { + JSArg::Value(value) => serde_serialize(value), + JSArg::Buffer(buf) => { + let array = Uint8Array::from(buf.as_slice()); + Ok(Buffer::from(&array).into()) + } + JSArg::Array(value) => { + let array = Array::new(); + for arg in value { + let js_arg = arg.to_js_value()?; + array.push(&js_arg); + } + + Ok(JsValue::from(array)) + } + } + } +} diff --git a/query-engine/driver-adapters/src/wasm/mod.rs b/query-engine/driver-adapters/src/wasm/mod.rs index 8a75f81d9280..7f51b1ee0236 100644 --- a/query-engine/driver-adapters/src/wasm/mod.rs +++ b/query-engine/driver-adapters/src/wasm/mod.rs @@ -1,10 +1,12 @@ //! Query Engine Driver Adapters: `wasm`-specific implementation. mod adapter_method; +mod conversion; mod error; mod from_js; mod js_object_extern; pub(crate) mod result; +mod to_js; pub(crate) use adapter_method::AdapterMethod; pub(crate) use from_js::FromJsValue; diff --git a/query-engine/driver-adapters/src/wasm/to_js.rs b/query-engine/driver-adapters/src/wasm/to_js.rs new file mode 100644 index 000000000000..4a76dee6a513 --- /dev/null +++ b/query-engine/driver-adapters/src/wasm/to_js.rs @@ -0,0 +1,27 @@ +use serde::Serialize; +use serde_wasm_bindgen::Serializer; +use wasm_bindgen::{JsError, JsValue}; + +// `serialize_missing_as_null` is required to make sure that "empty" values (e.g., `None` and `()`) +// are serialized as `null` and not `undefined`. +// This is due to certain drivers (e.g., LibSQL) not supporting `undefined` values. +static DEFAULT_SERIALIZER: Serializer = Serializer::new().serialize_missing_as_null(true); + +pub(crate) trait ToJsValue: Sized { + fn to_js_value(&self) -> Result; +} + +impl ToJsValue for T +where + T: Serialize, +{ + fn to_js_value(&self) -> Result { + serde_serialize(self) + } +} + +pub(crate) fn serde_serialize(value: T) -> Result { + value + .serialize(&DEFAULT_SERIALIZER) + .map_err(|err| JsValue::from(JsError::from(err))) +}