Skip to main content

Capability

Struct Capability 

Source
pub struct Capability {
Show 42 fields pub sql: bool, pub sql_placeholder: Option<SqlPlaceholder>, pub storage_types: StorageTypes, pub schema_mutations: SchemaMutations, pub cte_with_update: bool, pub select_for_update: bool, pub returning_from_mutation: bool, pub primary_key_ne_predicate: bool, pub auto_increment: bool, pub max_auto_increment_integer_width: Option<u8>, pub max_identifier_length: Option<usize>, pub native_varchar: bool, pub native_timestamp: bool, pub native_date: bool, pub native_time: bool, pub native_datetime: bool, pub native_enum: bool, pub named_enum_types: bool, pub native_decimal: bool, pub bigdecimal_implemented: bool, pub decimal_arbitrary_precision: bool, pub index_or_predicate: bool, pub native_starts_with: bool, pub glob_starts_with: bool, pub binary_like_starts_with: bool, pub native_like: bool, pub native_ilike: bool, pub scan: bool, pub scan_supports_sort: bool, pub test_connection_pool: bool, pub transaction_lock_mode: bool, pub backward_pagination: bool, pub bool_key_type: bool, pub bind_list_param: bool, pub predicate_match_any: bool, pub native_array: bool, pub vec_scalar: bool, pub document_collections: bool, pub native_array_set_predicates: bool, pub vec_remove: bool, pub vec_pop: bool, pub vec_remove_at: bool,
}
Expand description

Describes what a database driver supports.

The query planner reads these flags to decide which Operation variants to generate. For example, a SQL driver sets sql: true and receives QuerySql operations, while DynamoDB sets sql: false and receives key-value operations like GetByKey and QueryPk.

Pre-built configurations are available as associated constants: SQLITE, POSTGRESQL, MYSQL, and DYNAMODB.

§Examples

use toasty_core::driver::Capability;

let cap = &Capability::SQLITE;
assert!(cap.sql);
assert!(cap.returning_from_mutation);
assert!(!cap.select_for_update);

Fields§

§sql: bool

When true, the database uses a SQL-based query language and the planner will emit QuerySql operations.

§sql_placeholder: Option<SqlPlaceholder>

Placeholder syntax accepted by the driver’s SQL bind layer.

SQL drivers set this to Some. Non-SQL drivers set this to None.

§storage_types: StorageTypes

Column storage types supported by the database.

§schema_mutations: SchemaMutations

What the database is able to change about its own schema. See SchemaMutations for the individual fields; the migration generator branches on them to choose between an in-place ALTER COLUMN and a table rebuild, and between one combined alter statement and several single-property ones.

§cte_with_update: bool

SQL: supports update statements in CTE queries.

§select_for_update: bool

SQL: Supports row-level locking. If false, then the driver is expected to serializable transaction-level isolation.

§returning_from_mutation: bool

SQL: Mysql doesn’t support returning clauses from insert / update queries

§primary_key_ne_predicate: bool

DynamoDB does not support != predicates on the primary key.

§auto_increment: bool

Whether the database has an auto increment modifier for integer columns.

§max_auto_increment_integer_width: Option<u8>

Maximum storage width, in bytes, for auto-increment integer columns.

Backends that require a particular declared type for auto-increment columns use this to cap the storage type selected from the Rust field type. SQLite requires the declared type to be INTEGER when using AUTOINCREMENT; Toasty’s SQLite serializer emits that spelling for Integer(4).

§max_identifier_length: Option<usize>

Maximum byte length for a database identifier (table name, index name, column name, etc.).

When Some(n), auto-generated index names that exceed n bytes are truncated and a short stable hash suffix is appended so names remain unique and deterministic across builds. User-supplied #[index(name = "...")] names are left untouched.

  • MySQL: Some(64) — hard error on longer names
  • PostgreSQL: Some(63) — silently truncates, risking collisions
  • SQLite / DynamoDB: None — no enforced limit
§native_varchar: bool

Whether the database supports VARCHAR(n) column types natively.

Must be consistent with StorageTypes::varchar: when true, varchar must be Some; when false, varchar must be None. Use Capability::validate to check this invariant.

§native_timestamp: bool

Whether the database has native support for Timestamp types.

§native_date: bool

Whether the database has native support for Date types.

§native_time: bool

Whether the database has native support for Time types.

§native_datetime: bool

Whether the database has native support for DateTime types.

§native_enum: bool

Whether the database supports native enum types.

  • PostgreSQL: trueCREATE TYPE ... AS ENUM
  • MySQL: true — inline ENUM('a', 'b') column type
  • SQLite: false — uses TEXT + CHECK constraint
  • DynamoDB: false — plain string attribute
§named_enum_types: bool

Whether enum types are standalone named objects requiring separate DDL.

When true, migrations must emit CREATE TYPE / ALTER TYPE for enum types. When false, enum definitions are inline in column types.

  • PostgreSQL: trueCREATE TYPE <name> AS ENUM (...)
  • MySQL: false — inline ENUM('a', 'b') on the column
  • SQLite: false
  • DynamoDB: false
§native_decimal: bool

Whether the database has native support for Decimal types.

§bigdecimal_implemented: bool

Whether BigDecimal driver support is implemented. TODO: Remove this flag when PostgreSQL BigDecimal support is implemented. Currently only MySQL has implemented BigDecimal driver support.

§decimal_arbitrary_precision: bool

Whether the database’s decimal type supports arbitrary precision. When false, the decimal type requires fixed precision and scale to be specified upfront.

  • PostgreSQL: true (NUMERIC supports arbitrary precision)
  • MySQL: false (DECIMAL requires fixed precision/scale)
  • SQLite/DynamoDB: false (no native decimal support, stored as TEXT)
§index_or_predicate: bool

Whether OR is supported in index key conditions (e.g. DynamoDB KeyConditionExpression). DynamoDB: false. All other backends: true (SQL backends never use index key conditions).

§native_starts_with: bool

Whether the database has a native prefix-match operator that does not require LIKE-style escaping. When true, starts_with is left in the AST and the driver renders it natively (DynamoDB’s begins_with(), PostgreSQL’s ^@, SQLite’s GLOB, MySQL’s LIKE BINARY). When false, the lowering rewrites it to a LIKE expression — which requires native_like to be true.

§glob_starts_with: bool

Whether starts_with should be rendered as a SQLite GLOB 'prefix*' expression. When true, extract_params escapes GLOB metacharacters (*, ?, [) in the prefix and appends *; the serializer emits col GLOB ?. Implies native_starts_with.

§binary_like_starts_with: bool

Whether starts_with should be rendered as MySQL BINARY col LIKE ? ESCAPE '!'. When true, extract_params escapes LIKE metacharacters using ! as the escape char and appends %; the serializer emits BINARY col LIKE ? ESCAPE '!'. Implies native_starts_with.

§native_like: bool

Whether the database has a native LIKE expression. When false, Expr::Like cannot be sent to the driver; starts_with lowering will not produce one.

§native_ilike: bool

Whether the database has a native case-insensitive LIKE operator (ILIKE). Only PostgreSQL has one.

Toasty does not emulate ILIKE on backends that lack it: .ilike() is a pass-through to the database’s own operator. When native_ilike is false, the query-verify pass rejects a case-insensitive Expr::Like with an unsupported_feature error rather than silently degrading to plain LIKE, whose case behavior differs.

Implies native_like.

§scan: bool

Whether the driver can answer queries that don’t match any primary key or index — i.e. supports unindexed full-table reads.

SQL drivers set this to true: unindexed queries go through QuerySql, so the SQL engine handles them transparently. DynamoDB also sets this to true; the planner emits Operation::Scan for the unindexed case. A hypothetical pure key-value store with no full-scan capability would set this to false.

§scan_supports_sort: bool

Whether scan operations support ordering results.

SQL drivers do not use Operation::Scan, so this is true for them (ordering is handled inside QuerySql). DynamoDB’s Scan API returns items in an arbitrary order with no server-side sort, so this is false for DynamoDB. When false, the planner rejects queries that combine a scan path with ORDER BY.

§test_connection_pool: bool

Whether to test connection pool behavior. TODO: We only need this for the connection_per_clone.rs test, come up with a better way.

§transaction_lock_mode: bool

Whether the driver honors non-Default TransactionMode variants (Immediate, Exclusive). Currently true only for SQLite, which maps them to BEGIN IMMEDIATE / BEGIN EXCLUSIVE. Drivers that leave this false reject non-Default modes with Error::unsupported_feature.

§backward_pagination: bool

Whether the backend can walk a paginated query in reverse from a cursor.

Gates the prev_cursor field on a Page returned to user code. When true, the executor extracts a previous-page cursor from the first row of every page (see apply_sql_pagination in toasty/src/engine/exec/exec_statement.rs). When false, the executor leaves prev_cursor as None, so Page::has_prev() returns false and Page::prev(&db) resolves to Ok(None) without issuing a query. Paginate::before(cursor) itself is not rejected — users who already hold a cursor can walk backwards explicitly — but a driver that returns false is declaring that it has no way to produce such a cursor.

Drivers should set this to true when the backend can answer a query equivalent to “rows ordered by K, descending from K = c, limited to N” — i.e. the same ORDER BY clause reversed plus a strict inequality on the cursor key. SQL backends meet this trivially. DynamoDB does not: a Query with ScanIndexForward = false returns rows in the opposite direction but cannot be rooted at an arbitrary client-supplied cursor without an extra KeyConditionExpression, and Scan has no order guarantee at all.

§bool_key_type: bool

Whether the backend supports BOOL as a key attribute type.

DynamoDB only allows S, N, or B for primary-key and GSI key attribute types; BOOL is rejected at the API level. SQL backends have no such restriction. When false, the schema builder overrides storage_ty for any Bool key/index field to db::Type::Integer(1), letting the engine cast Bool ↔ I8 and the driver handle it as a plain number — no driver-level bool-to-number special-casing needed.

§bind_list_param: bool

The driver’s bind layer accepts a single parameter whose value is Value::List(items) and type is Type::List(elem), sending it as one protocol-level parameter (not N separate scalars). Property of the driver bind impl, not the SQL dialect.

§predicate_match_any: bool

The SQL dialect parses expr <op> ANY(<array>) and expr <op> ALL(<array>) as predicates against an array-valued operand. Property of the dialect, not the bind layer.

§native_array: bool

Whether the database can store a Vec<scalar> model field as a native array column (e.g. PostgreSQL text[], int8[]).

When true, schema build maps Type::List(elem) to db::Type::List(elem) and the driver’s bind layer accepts Value::List(items) as a single array-valued parameter.

When false, Vec<T> model fields use whatever fallback the backend provides (JSON column on MySQL/SQLite, native List L on DynamoDB). See Self::vec_scalar for the schema-build gate.

§vec_scalar: bool

Whether the driver supports Vec<scalar> model fields, by whatever representation (native typed array column, JSON column, key-value list attribute, …). Used by the schema builder as the gate for accepting stmt::Type::List(_) fields.

§document_collections: bool

Whether the driver can store a #[document] collection field — a Vec<T> of an embedded struct — as a single document column (jsonb / JSON on the SQL backends). Used by the schema builder as the gate for accepting stmt::Type::List(Document(_)) fields.

§native_array_set_predicates: bool

Whether the driver natively renders IsSuperset / Intersects array predicates over an arbitrary right-hand-side expression.

SQL drivers set this to true: each dialect has a single operator (@> on PostgreSQL, JSON_CONTAINS on MySQL, a json_each subquery on SQLite) that takes the rhs as a bound expression regardless of its shape.

DynamoDB sets this to false: it has no equivalent operator and emulates the predicates by emitting one contains(path, vN) clause per rhs element, which requires the rhs to be a concrete list of values at filter-construction time. The capability check rejects any other rhs shape before the driver is invoked.

§vec_remove: bool

Whether the driver supports atomic in-place removal of every element equal to a given value from a Vec<scalar> field (stmt::remove).

  • PostgreSQL text[]: truearray_remove(col, v).
  • MySQL / SQLite JSON: false — no value-removal operator.
  • DynamoDB List: false — no value-removal on Lists.
§vec_pop: bool

Whether the driver supports atomic in-place removal of the last element of a Vec<scalar> field (stmt::pop).

  • PostgreSQL: true — array slicing.
  • MySQL / SQLite: false.
  • DynamoDB: falseUpdateExpression indices must be literal integers, so the last index cannot be expressed in one statement.
§vec_remove_at: bool

Whether the driver supports atomic in-place removal of an element at a given index from a Vec<scalar> field (stmt::remove_at).

  • PostgreSQL: true — array slicing.
  • MySQL / SQLite: false.
  • DynamoDB: false.

Implementations§

Source§

impl Capability

Source

pub const SQLITE: Self

SQLite capabilities.

Source

pub const POSTGRESQL: Self

PostgreSQL capabilities

Source

pub const MYSQL: Self

MySQL capabilities

Source

pub const TURSO: Self

Turso capabilities.

Identical to SQLITE at the flag level. The driver extends SQLite’s behavior in two ways that don’t fit a capability bit:

  • It opens a real async connection per pool slot (sharing a cached Database across connect() calls), so the connection-pool test suite applies.
  • When Turso::concurrent_writes() is enabled, the driver issues BEGIN CONCURRENT for TransactionMode::Default, opting the transaction into Turso’s MVCC concurrency. The other TransactionMode variants pass through to the SQLite serializer unchanged, so callers can still request the classic locking strategies per transaction.
Source

pub const DYNAMODB: Self

DynamoDB capabilities

Source

pub fn validate(&self) -> Result<()>

Validates the consistency of the capability configuration.

This performs sanity checks to ensure the capability fields are internally consistent. For example, if native_varchar is true, then storage_types.varchar must be Some, and vice versa.

Returns an error if any inconsistencies are found.

Source

pub fn default_string_max_length(&self) -> Option<u64>

Returns the default string length limit for this database.

This is useful for tests and applications that need to respect database-specific string length constraints.

Source

pub fn native_type_for(&self, ty: &Type) -> Type

Returns the native database type for an application-level type.

If the database supports the type natively, returns the same type. Otherwise, returns the bridge/storage type that the application type maps to in this database.

This uses the existing db::Type::bridge_type() method to determine the appropriate bridge type based on the database’s storage capabilities.

Trait Implementations§

Source§

impl Debug for Capability

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more