#[non_exhaustive]pub enum ScalarFieldType {
Text,
Integer,
Numeric,
Boolean,
DateTime,
Date,
Time,
Uuid,
Vector,
}Expand description
Declared scalar type of a JSON field, used to pick the SQL cast.
A JSON/JSONB extraction is always text, so both ORDER BY and WHERE have to
cast it before the database can compare it as anything else. Sorting "9"
after "10" is the visible symptom for numbers; for WHERE the symptom is a
wrong row set (or a hard cast error).
The variant → SQL-type-name mapping lives in exactly one place —
SqlDialect::cast_type_name — so ORDER BY and WHERE cannot drift apart.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Text
No cast — text comparison (correct for strings, UUIDs, IDs, enum values).
Integer
Integer (::bigint / CAST(… AS BIGINT)).
Numeric
Fixed/floating point (::numeric / CAST(… AS DECIMAL(38,12))).
Boolean
Boolean (::boolean).
DateTime
Instant (::timestamptz / CAST(… AS DATETIME2)).
Date
Calendar date (::date).
Time
Wall-clock time (::time).
Uuid
Identity comparison (ID/UUID) — no cast.
Renders exactly like Self::Text; the variant exists to mark which
fields are identities, not to introduce a cast. cast_type_name returns
None for it deliberately.
Casting would be the obvious repair and is the wrong one:
(data->>'id')::uuid is evaluated per row, so one row holding a
non-UUID identity raises SQLSTATE 22P02 for every query — and ID is
documented as intentionally spanning uuid / integer / text keys
(docs/adr/0017-entity-identity-contract.md), with fixtures holding
'user-1' and a BIGINT pk. Equality is instead made case-insensitive at
the literal, which needs no knowledge of the column’s type.
Vector
A declared pgvector field — vector(N), halfvec(N), sparsevec(N) or
bit(N) (#1117).
Like Self::Uuid, this marks which fields are of a kind rather than
introducing a cast: cast_type_name returns None for it, so every
ordinary comparison against a vector field renders exactly as it did.
What it decides is the operand a distance predicate reads. The
storage contract requires the backing view to expose a vector as a native
column, and nearest has always ordered by it; the threshold operators
could not tell a vector field from any other, so they resolved it through
data->> and re-parsed every row’s embedding out of text — 2667 ms
against the column’s 22 ms, on the same 400 rows.
One variant covers all four pgvector types on purpose: which pgvector
type the literal is cast to is decided by the operand’s own shape (an
array is ::vector, {1:0.5}/1000 is ::sparsevec, the binary metrics
are ::varbit), and that is unchanged by this. What the schema is being
asked here is only “is there a native column to read instead of the
JSONB text?”.
Trait Implementations§
Source§impl Clone for ScalarFieldType
impl Clone for ScalarFieldType
impl Copy for ScalarFieldType
Source§impl Debug for ScalarFieldType
impl Debug for ScalarFieldType
Source§impl Default for ScalarFieldType
impl Default for ScalarFieldType
Source§impl<'de> Deserialize<'de> for ScalarFieldType
impl<'de> Deserialize<'de> for ScalarFieldType
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for ScalarFieldType
Source§impl PartialEq for ScalarFieldType
impl PartialEq for ScalarFieldType
Source§impl Serialize for ScalarFieldType
impl Serialize for ScalarFieldType
impl StructuralPartialEq for ScalarFieldType
Auto Trait Implementations§
impl Freeze for ScalarFieldType
impl RefUnwindSafe for ScalarFieldType
impl Send for ScalarFieldType
impl Sync for ScalarFieldType
impl Unpin for ScalarFieldType
impl UnsafeUnpin for ScalarFieldType
impl UnwindSafe for ScalarFieldType
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.