Skip to content

Commit

Permalink
feat(sql-schema-connector): wasm-compatible sql-schema-connector (#…
Browse files Browse the repository at this point in the history
…5126)

* feat(sql-schema-connector): enable wasm compilation with "--features sqlite"

* feat(sql-schema-connector): enable wasm compilation with "--features postgresql" and "--features cockroachdb"

* feat(sql-schema-connector): get rid of sql-schema-connector-wasm

* fix(sql-schema-connector): remove typo, fix migration tests

* feat(sql-schema-connector): expose external constructors for postgres, sqlite

* feat(sql-schema-connector): enable wasm compilation with "--features mysql"

* chore: remove typo

* feat(sql-schema-connector): enable wasm compilation with "--features mssql"; update mssql's quaint::visitor::Visitor

* chore(schema-engine-wasm): typo

---------

Co-authored-by: jkomyno <[email protected]>
  • Loading branch information
jkomyno and jkomyno authored Jan 16, 2025
1 parent c164b5d commit 2b21c24
Show file tree
Hide file tree
Showing 42 changed files with 854 additions and 147 deletions.
4 changes: 3 additions & 1 deletion quaint/src/ast/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ impl Function<'_> {
}
}

/// A database function type
/// A database function type.
/// Not every function is supported by every database.
/// TODO: Use `cfg` compilation flags to enable/disable functions based on the database family.
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum FunctionType<'a> {
RowToJson(RowToJson<'a>),
Expand Down
2 changes: 2 additions & 0 deletions quaint/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ pub trait Visitor<'a> {
/// Visit a non-parameterized value.
fn visit_raw_value(&mut self, value: Value<'a>) -> Result;

// TODO: JSON functions such as this one should only be required when
// `#[cfg(any(feature = "postgresql", feature = "mysql"))]` or similar filters apply.
fn visit_json_extract(&mut self, json_extract: JsonExtract<'a>) -> Result;

fn visit_json_extract_last_array_item(&mut self, extract: JsonExtractLastArrayElem<'a>) -> Result;
Expand Down
12 changes: 0 additions & 12 deletions quaint/src/visitor/mssql.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use super::{NativeColumnType, Visitor};
#[cfg(any(feature = "postgresql", feature = "mysql"))]
use crate::prelude::{JsonArrayAgg, JsonBuildObject, JsonExtract, JsonType, JsonUnquote};
use crate::{
ast::{
Expand Down Expand Up @@ -672,12 +671,10 @@ impl<'a> Visitor<'a> for Mssql<'a> {
Ok(())
}

#[cfg(any(feature = "postgresql", feature = "mysql"))]
fn visit_json_extract(&mut self, _json_extract: JsonExtract<'a>) -> visitor::Result {
unimplemented!("JSON filtering is not yet supported on MSSQL")
}

#[cfg(any(feature = "postgresql", feature = "mysql"))]
fn visit_json_array_contains(
&mut self,
_left: Expression<'a>,
Expand All @@ -687,32 +684,26 @@ impl<'a> Visitor<'a> for Mssql<'a> {
unimplemented!("JSON filtering is not yet supported on MSSQL")
}

#[cfg(any(feature = "postgresql", feature = "mysql"))]
fn visit_json_type_equals(&mut self, _left: Expression<'a>, _json_type: JsonType, _not: bool) -> visitor::Result {
unimplemented!("JSON_TYPE is not yet supported on MSSQL")
}

#[cfg(any(feature = "postgresql", feature = "mysql"))]
fn visit_json_unquote(&mut self, _json_unquote: JsonUnquote<'a>) -> visitor::Result {
unimplemented!("JSON filtering is not yet supported on MSSQL")
}

#[cfg(feature = "postgresql")]
fn visit_json_array_agg(&mut self, _array_agg: JsonArrayAgg<'a>) -> visitor::Result {
unimplemented!("JSON_AGG is not yet supported on MSSQL")
}

#[cfg(feature = "postgresql")]
fn visit_json_build_object(&mut self, _build_obj: JsonBuildObject<'a>) -> visitor::Result {
unimplemented!("JSON_BUILD_OBJECT is not yet supported on MSSQL")
}

#[cfg(feature = "postgresql")]
fn visit_text_search(&mut self, _text_search: crate::prelude::TextSearch<'a>) -> visitor::Result {
unimplemented!("Full-text search is not yet supported on MSSQL")
}

#[cfg(feature = "postgresql")]
fn visit_matches(
&mut self,
_left: Expression<'a>,
Expand All @@ -722,23 +713,20 @@ impl<'a> Visitor<'a> for Mssql<'a> {
unimplemented!("Full-text search is not yet supported on MSSQL")
}

#[cfg(feature = "postgresql")]
fn visit_text_search_relevance(
&mut self,
_text_search_relevance: crate::prelude::TextSearchRelevance<'a>,
) -> visitor::Result {
unimplemented!("Full-text search is not yet supported on MSSQL")
}

#[cfg(any(feature = "postgresql", feature = "mysql"))]
fn visit_json_extract_last_array_item(
&mut self,
_extract: crate::prelude::JsonExtractLastArrayElem<'a>,
) -> visitor::Result {
unimplemented!("JSON filtering is not yet supported on MSSQL")
}

#[cfg(any(feature = "postgresql", feature = "mysql"))]
fn visit_json_extract_first_array_item(
&mut self,
_extract: crate::prelude::JsonExtractFirstArrayElem<'a>,
Expand Down
4 changes: 3 additions & 1 deletion query-engine/connector-test-kit-rs/qe-setup/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ psl.workspace = true
quaint.workspace = true
mongodb-client = { path = "../../../libs/mongodb-client" }
schema-core = { path = "../../../schema-engine/core" }
sql-schema-connector = { path = "../../../schema-engine/connectors/sql-schema-connector" }
sql-schema-connector = { path = "../../../schema-engine/connectors/sql-schema-connector", features = [
"all-native",
] }
test-setup = { path = "../../../libs/test-setup" }
enumflags2.workspace = true
serde.workspace = true
Expand Down
49 changes: 30 additions & 19 deletions schema-engine/connectors/sql-schema-connector/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,44 @@ version = "0.1.0"

[features]
vendored-openssl = ["quaint/vendored-openssl"]
postgresql = ["psl/postgresql", "quaint/postgresql", "schema-connector/postgresql", "sql-schema-describer/postgresql"]
postgresql-native = ["postgresql", "quaint/postgresql-native", "quaint/pooled"]
sqlite = ["psl/sqlite", "quaint/sqlite", "schema-connector/sqlite", "sql-schema-describer/sqlite"]
sqlite-native = ["sqlite", "quaint/sqlite-native", "quaint/pooled", "quaint/expose-drivers", "sqlx-sqlite", "sqlx-core"]
mysql = ["psl/mysql", "quaint/mysql", "schema-connector/mysql", "sql-schema-describer/mysql"]
mysql-native = ["mysql", "quaint/mysql-native", "quaint/pooled"]
mssql = ["psl/mssql", "quaint/mssql", "schema-connector/mssql", "sql-schema-describer/mssql"]
mssql-native = ["mssql", "quaint/mssql-native", "quaint/pooled"]
cockroachdb = ["psl/cockroachdb", "quaint/postgresql", "schema-connector/cockroachdb", "sql-schema-describer/cockroachdb"]
cockroachdb-native = ["cockroachdb", "quaint/postgresql-native", "quaint/pooled"]
all-native = [
"vendored-openssl",
"quaint/fmt-sql",
"postgresql-native",
"sqlite-native",
"mysql-native",
"mssql-native",
"cockroachdb-native",
"schema-connector/all-native",
"sql-schema-describer/all-native",
"user-facing-errors/all-native",
]

[dependencies]
psl.workspace = true
quaint = { workspace = true, features = [
"all-native",
"expose-drivers",
"pooled",
"fmt-sql",
] }
tokio.workspace = true
quaint.workspace = true
tokio = { version = "1", features = ["macros", "sync", "io-util", "time"] }
serde.workspace = true
indoc.workspace = true
uuid.workspace = true
indexmap.workspace = true

prisma-value = { path = "../../../libs/prisma-value" }
schema-connector = { path = "../schema-connector", features = [
"all-native",
] }
sql-schema-describer = { path = "../../sql-schema-describer", features = [
"all-native",
] }
schema-connector = { path = "../schema-connector" }
sql-schema-describer = { path = "../../sql-schema-describer" }
datamodel-renderer = { path = "../../datamodel-renderer" }
sql-ddl = { path = "../../../libs/sql-ddl" }
user-facing-errors = { path = "../../../libs/user-facing-errors", features = [
"sql",
"all-native",
] }
user-facing-errors = { path = "../../../libs/user-facing-errors", features = ["sql"] }

chrono.workspace = true
connection-string.workspace = true
Expand All @@ -47,7 +57,8 @@ either = "1.6"
sqlformat = "0.2.1"
sqlparser = "0.32.0"
versions = "6.1.0"
sqlx-sqlite = { version = "0.8.0" }
sqlx-core = "0.8.0"
sqlx-sqlite = { version = "0.8.0", optional = true }
sqlx-core = { version = "0.8.0", optional = true }

[dev-dependencies]
expect-test = "1"
14 changes: 14 additions & 0 deletions schema-engine/connectors/sql-schema-connector/src/flavour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@
//! in order to avoid cluttering the connector with conditionals. This is a private implementation
//! detail of the SQL connector.
#[cfg(feature = "mssql")]
mod mssql;

#[cfg(feature = "mysql")]
mod mysql;

#[cfg(any(feature = "postgresql", feature = "cockroachdb"))]
mod postgres;

#[cfg(feature = "sqlite")]
mod sqlite;

#[cfg(feature = "mssql")]
pub(crate) use mssql::MssqlFlavour;

#[cfg(feature = "mysql")]
pub(crate) use mysql::MysqlFlavour;

#[cfg(any(feature = "postgresql", feature = "cockroachdb"))]
pub(crate) use postgres::PostgresFlavour;

#[cfg(feature = "sqlite")]
pub(crate) use sqlite::SqliteFlavour;

use crate::{
Expand Down
14 changes: 11 additions & 3 deletions schema-engine/connectors/sql-schema-connector/src/flavour/mssql.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
mod connection;
mod shadow_db;
#[cfg(feature = "mssql-native")]
mod native;

#[cfg(not(feature = "mssql-native"))]
mod wasm;

#[cfg(feature = "mssql-native")]
use native::{generic_apply_migration_script, shadow_db, Connection};

#[cfg(not(feature = "mssql-native"))]
use wasm::{generic_apply_migration_script, shadow_db, Connection};

use self::connection::*;
use crate::SqlFlavour;
use connection_string::JdbcString;
use indoc::formatdoc;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! All the quaint-wrangling for the mssql connector should happen here.
pub(super) mod shadow_db;

use quaint::{
connector::{self, MssqlUrl},
prelude::{ConnectionInfo, NativeConnectionInfo, Queryable},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::flavour::*;
use schema_connector::{migrations_directory::MigrationDirectory, ConnectorResult};
use crate::flavour::{MssqlFlavour, SqlFlavour};
use schema_connector::{migrations_directory::MigrationDirectory, ConnectorError, ConnectorResult, Namespaces};
use sql_schema_describer::SqlSchema;

pub(super) async fn sql_schema_from_migrations_history(
pub async fn sql_schema_from_migrations_history(
migrations: &[MigrationDirectory],
mut shadow_db: MssqlFlavour,
namespaces: Option<Namespaces>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//! All the quaint-wrangling for the mssql connector should happen here.
pub(super) mod shadow_db;

use enumflags2::BitFlags;
use quaint::connector::{ColumnType, DescribedColumn, DescribedParameter, GetRow, MssqlUrl, ToColumnNames};
use schema_connector::{BoxFuture, ConnectorError, ConnectorResult, Namespaces};
use sql_schema_describer::{mssql as describer, DescriberErrorKind, SqlSchema};
use user_facing_errors::schema_engine::ApplyMigrationError;

// TODO: use ExternalConnector here.
pub(super) struct Connection();

impl Connection {
pub(super) async fn new(connection_str: &str) -> ConnectorResult<Self> {
panic!("[sql-schema-connector::flavour::mssql::wasm] Not implemented");
}

#[tracing::instrument(skip(self, params))]
pub(super) async fn describe_schema(
&mut self,
params: &super::Params,
namespaces: Option<Namespaces>,
) -> ConnectorResult<SqlSchema> {
panic!("[sql-schema-connector::flavour::mssql::wasm] Not implemented");
}

pub(super) async fn raw_cmd(&mut self, sql: &str, params: &super::Params) -> ConnectorResult<()> {
tracing::debug!(query_type = "raw_cmd", sql);
panic!("[sql-schema-connector::flavour::mssql::wasm] Not implemented");
}

pub(super) async fn version(&mut self, params: &super::Params) -> ConnectorResult<Option<String>> {
tracing::debug!(query_type = "version");
panic!("[sql-schema-connector::flavour::mssql::wasm] Not implemented");
}

pub(super) async fn query(
&mut self,
query: quaint::ast::Query<'_>,
conn_params: &super::Params,
) -> ConnectorResult<quaint::prelude::ResultSet> {
use quaint::visitor::Visitor;
let (sql, params) = quaint::visitor::Mssql::build(query).unwrap();
self.query_raw(&sql, &params, conn_params).await
}

pub(super) async fn query_raw(
&mut self,
sql: &str,
params: &[quaint::prelude::Value<'_>],
conn_params: &super::Params,
) -> ConnectorResult<quaint::prelude::ResultSet> {
tracing::debug!(query_type = "query_raw", sql);
panic!("[sql-schema-connector::flavour::mssql::wasm] Not implemented");
}
}

pub(super) async fn generic_apply_migration_script(
migration_name: &str,
script: &str,
conn: &mut Connection,
) -> ConnectorResult<()> {
tracing::debug!(query_type = "raw_cmd", script);
panic!("[sql-schema-connector::flavour::mssql::wasm] Not implemented");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::flavour::{MssqlFlavour, SqlFlavour};
use schema_connector::Namespaces;
use schema_connector::{migrations_directory::MigrationDirectory, ConnectorResult};
use sql_schema_describer::SqlSchema;

pub async fn sql_schema_from_migrations_history(
migrations: &[MigrationDirectory],
mut shadow_db: MssqlFlavour,
namespaces: Option<Namespaces>,
) -> ConnectorResult<SqlSchema> {
panic!("[sql-schema-connector::flavour::mssql::wasm] Not implemented");
}
14 changes: 11 additions & 3 deletions schema-engine/connectors/sql-schema-connector/src/flavour/mysql.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
mod connection;
mod shadow_db;
#[cfg(feature = "mysql-native")]
mod native;

#[cfg(not(feature = "mysql-native"))]
mod wasm;

#[cfg(feature = "mysql-native")]
use native::{shadow_db, Connection};

#[cfg(not(feature = "mysql-native"))]
use wasm::{shadow_db, Connection};

use self::connection::*;
use crate::{error::SystemDatabase, flavour::SqlFlavour};
use enumflags2::BitFlags;
use indoc::indoc;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! All the quaint-wrangling for the mysql connector should happen here.
pub(super) mod shadow_db;

use enumflags2::BitFlags;
use quaint::{
connector::{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::flavour::*;
use crate::flavour::{mysql, MysqlFlavour, SqlFlavour};
use schema_connector::{migrations_directory::MigrationDirectory, ConnectorResult};
use sql_schema_describer::SqlSchema;

pub(super) async fn sql_schema_from_migrations_history(
pub async fn sql_schema_from_migrations_history(
migrations: &[MigrationDirectory],
mut shadow_db: MysqlFlavour,
) -> ConnectorResult<SqlSchema> {
Expand All @@ -14,7 +14,7 @@ pub(super) async fn sql_schema_from_migrations_history(
migration.migration_name()
);

super::scan_migration_script_impl(&script);
mysql::scan_migration_script_impl(&script);

shadow_db
.apply_migration_script(migration.migration_name(), &script)
Expand Down
Loading

0 comments on commit 2b21c24

Please sign in to comment.