-
Notifications
You must be signed in to change notification settings - Fork 313
feat: add SurrealDB support (PSL, query compiler, schema engine) #5798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4b1d0b3
3b3f2cf
df5613b
99e5ccc
e3f0656
a89696f
2fe5a1f
66b0765
e2a377e
d28c8ba
f39f014
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| use std::borrow::Cow; | ||
|
|
||
| use crate::{ | ||
| ValidatedSchema, | ||
| datamodel_connector::{ | ||
| Connector, ConnectorCapabilities, ConnectorCapability, ConstraintScope, Flavour, NativeTypeConstructor, | ||
| NativeTypeInstance, | ||
| }, | ||
| diagnostics::{DatamodelError, Diagnostics, Span}, | ||
| parser_database::ReferentialAction, | ||
| }; | ||
| use enumflags2::BitFlags; | ||
| use parser_database::{ExtensionTypes, ScalarFieldType}; | ||
|
|
||
| const NATIVE_TYPE_CONSTRUCTORS: &[NativeTypeConstructor] = &[]; | ||
| const CONSTRAINT_SCOPES: &[ConstraintScope] = &[ConstraintScope::GlobalKeyIndex]; | ||
|
|
||
| pub const CAPABILITIES: ConnectorCapabilities = enumflags2::make_bitflags!(ConnectorCapability::{ | ||
| AnyId | | ||
| CompoundIds | | ||
| RelationFieldsInArbitraryOrder | | ||
| UpdateableId | | ||
| DecimalType | | ||
| BackwardCompatibleQueryRaw | | ||
| NativeUpsert | | ||
| FilteredInlineChildNestedToOneDisconnect | | ||
| InsertReturning | | ||
| DeleteReturning | | ||
| UpdateReturning | | ||
| SupportsFiltersOnRelationsWithoutJoins | | ||
| CreateMany | | ||
| Json | | ||
| AdvancedJsonNullability | ||
| }); | ||
|
|
||
| pub struct SurrealDbDatamodelConnector; | ||
|
|
||
| impl Connector for SurrealDbDatamodelConnector { | ||
| fn provider_name(&self) -> &'static str { | ||
| "surrealdb" | ||
| } | ||
|
|
||
| fn name(&self) -> &str { | ||
| "SurrealDB" | ||
| } | ||
|
|
||
| fn capabilities(&self) -> ConnectorCapabilities { | ||
| CAPABILITIES | ||
| } | ||
|
|
||
| fn max_identifier_length(&self) -> usize { | ||
| // SurrealDB does not impose a specific identifier length limit | ||
| 10000 | ||
| } | ||
|
|
||
| fn foreign_key_referential_actions(&self) -> BitFlags<ReferentialAction> { | ||
| // SurrealDB does not support foreign key constraints natively | ||
| BitFlags::empty() | ||
| } | ||
|
|
||
| fn emulated_referential_actions(&self) -> BitFlags<ReferentialAction> { | ||
| use ReferentialAction::*; | ||
|
|
||
| Restrict | SetNull | Cascade | ||
| } | ||
|
|
||
| fn scalar_type_for_native_type( | ||
| &self, | ||
| _native_type: &NativeTypeInstance, | ||
| _extension_types: &dyn ExtensionTypes, | ||
| ) -> Option<ScalarFieldType> { | ||
| // Unreachable: parse_native_type() always returns None and | ||
| // available_native_type_constructors() is empty, so the validation | ||
| // pipeline in fields.rs never calls this method for SurrealDB. | ||
| unreachable!("No native types on SurrealDB"); | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| fn default_native_type_for_scalar_type( | ||
| &self, | ||
| _scalar_type: &ScalarFieldType, | ||
| _schema: &ValidatedSchema, | ||
| ) -> Option<NativeTypeInstance> { | ||
| None | ||
| } | ||
|
|
||
| fn native_type_to_parts<'t>(&self, _native_type: &'t NativeTypeInstance) -> (&'t str, Cow<'t, [String]>) { | ||
| unreachable!() | ||
| } | ||
|
|
||
| fn constraint_violation_scopes(&self) -> &'static [ConstraintScope] { | ||
| CONSTRAINT_SCOPES | ||
| } | ||
|
|
||
| fn available_native_type_constructors(&self) -> &'static [NativeTypeConstructor] { | ||
| NATIVE_TYPE_CONSTRUCTORS | ||
| } | ||
|
|
||
| fn parse_native_type( | ||
| &self, | ||
| _name: &str, | ||
| _args: &[String], | ||
| span: Span, | ||
| diagnostics: &mut Diagnostics, | ||
| ) -> Option<NativeTypeInstance> { | ||
| diagnostics.push_error(DatamodelError::new_native_types_not_supported( | ||
| self.name().to_owned(), | ||
| span, | ||
| )); | ||
| None | ||
| } | ||
|
|
||
| fn validate_url(&self, url: &str) -> Result<(), String> { | ||
| // surrealdb:// is the canonical scheme; http(s):// accepted for direct HTTP API access. | ||
| if url.starts_with("surrealdb://") || url.starts_with("http://") || url.starts_with("https://") { | ||
| Ok(()) | ||
| } else { | ||
| Err("must start with the protocol `surrealdb://`, `http://`, or `https://`.".to_string()) | ||
| } | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| fn flavour(&self) -> Flavour { | ||
| Flavour::SurrealDb | ||
| } | ||
|
|
||
| fn can_assume_strict_equality_in_joins(&self) -> bool { | ||
| true | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -323,6 +323,7 @@ pub enum Flavour { | |
| Mysql, | ||
| Postgres, | ||
| Sqlite, | ||
| SurrealDb, | ||
| } | ||
|
|
||
| impl Flavour { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -414,6 +414,8 @@ pub enum SqlFamily { | |
| Sqlite, | ||
| #[cfg(feature = "mssql")] | ||
| Mssql, | ||
| #[cfg(feature = "surrealdb")] | ||
| SurrealDb, | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| impl SqlFamily { | ||
|
|
@@ -428,6 +430,8 @@ impl SqlFamily { | |
| SqlFamily::Sqlite => "sqlite", | ||
| #[cfg(feature = "mssql")] | ||
| SqlFamily::Mssql => "mssql", | ||
| #[cfg(feature = "surrealdb")] | ||
| SqlFamily::SurrealDb => "surrealdb", | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -440,6 +444,8 @@ impl SqlFamily { | |
| "postgres" | "postgresql" => Some(SqlFamily::Postgres), | ||
| #[cfg(feature = "mysql")] | ||
| "mysql" => Some(SqlFamily::Mysql), | ||
| #[cfg(feature = "surrealdb")] | ||
| "surrealdb" | "ws" | "wss" => Some(SqlFamily::SurrealDb), | ||
| _ => None, | ||
| } | ||
| } | ||
|
|
@@ -455,6 +461,8 @@ impl SqlFamily { | |
| SqlFamily::Sqlite => Some(999), | ||
| #[cfg(feature = "mssql")] | ||
| SqlFamily::Mssql => Some(1000), | ||
| #[cfg(feature = "surrealdb")] | ||
| SqlFamily::SurrealDb => None, | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -501,6 +509,10 @@ impl SqlFamily { | |
| SqlFamily::Sqlite => 999, | ||
| #[cfg(feature = "mssql")] | ||
| SqlFamily::Mssql => 2098, | ||
| // SurrealDB has no documented parameter limit; this is a conservative | ||
| // transport-based fallback (HTTP/WebSocket body size dependent). | ||
| #[cfg(feature = "surrealdb")] | ||
| SqlFamily::SurrealDb => 32766, | ||
|
Comment on lines
+514
to
+515
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: SurrealDB does not document a hard limit on the number of query parameters or bind values. Official documentation on parameters (SurrealQL parameters page) describes usage but specifies no maximum count. Environment variables include a "Limits config" section, but no specific parameter or bind limit is detailed. Related limits exist in storage (e.g., SurrealKV key size, increased in recent fixes for vectors) and HTTP (e.g., Python SDK URL query length ~65KB, request body 16KiB configurable via future args). Client-side issues like WebSocket max size (default 1MB, configurable) affect large binds indirectly. For production, practical limits depend on transport (HTTP/WS body size, memory) rather than a fixed parameter count; use SDK bind methods to avoid injection and size issues. Citations:
SurrealDB has no documented maximum parameter limit; reconsider the hardcoded value. SurrealDB does not document a hard limit on query parameters or bind values. The current value of 🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
|
|
||
|
|
@@ -556,6 +568,18 @@ impl SqlFamily { | |
| pub fn is_mssql(&self) -> bool { | ||
| false | ||
| } | ||
|
|
||
| /// True, if family is SurrealDB. | ||
| #[cfg(feature = "surrealdb")] | ||
| pub fn is_surrealdb(&self) -> bool { | ||
| matches!(self, SqlFamily::SurrealDb) | ||
| } | ||
|
|
||
| /// True, if family is SurrealDB. | ||
| #[cfg(not(feature = "surrealdb"))] | ||
| pub fn is_surrealdb(&self) -> bool { | ||
| false | ||
| } | ||
| } | ||
|
|
||
| impl fmt::Display for SqlFamily { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.