Fix distinct type row mapping
This commit is contained in:
@@ -289,6 +289,10 @@ Nim Type Postgres Type SQLite Type
|
|||||||
`JsonNode`_ `jsonb`_
|
`JsonNode`_ `jsonb`_
|
||||||
=============== ====================== =================
|
=============== ====================== =================
|
||||||
|
|
||||||
|
Distinct types backed by a supported type are parsed through their backing
|
||||||
|
type and then converted to the distinct type. This also applies when the
|
||||||
|
distinct type is nested in an `Option`_ or `seq`.
|
||||||
|
|
||||||
.. [#f1] Note that this implies that all `NULL`-able fields should be typed
|
.. [#f1] Note that this implies that all `NULL`-able fields should be typed
|
||||||
as optional using `Option[fieldType]`. Conversely, any fields with
|
as optional using `Option[fieldType]`. Conversely, any fields with
|
||||||
non-optional types should also be constrained to be `NOT NULL` in
|
non-optional types should also be constrained to be `NOT NULL` in
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ requires "namespaced_logging >= 2.0.2"
|
|||||||
|
|
||||||
task unittest, "Runs the unit test suite.":
|
task unittest, "Runs the unit test suite.":
|
||||||
exec "nim c -r --path:src tests/test_datetime"
|
exec "nim c -r --path:src tests/test_datetime"
|
||||||
|
exec "nim c -r --path:src tests/test_distinct"
|
||||||
|
|
||||||
task integrationtest, "Runs the PostgreSQL integration test suite.":
|
task integrationtest, "Runs the PostgreSQL integration test suite.":
|
||||||
exec "nim c -r --path:src tests/test_datetime_postgres"
|
exec "nim c -r --path:src tests/test_datetime_postgres"
|
||||||
|
|||||||
@@ -266,10 +266,9 @@ func createParseStmt*(t, value: NimNode): NimNode =
|
|||||||
else: error "Cannot parse column with unknown generic instance type: " & $t.getTypeInst
|
else: error "Cannot parse column with unknown generic instance type: " & $t.getTypeInst
|
||||||
|
|
||||||
elif t.typeKind == ntyDistinct:
|
elif t.typeKind == ntyDistinct:
|
||||||
result = quote do:
|
let baseType = t.getTypeImpl[0]
|
||||||
block:
|
let parseStmt = createParseStmt(baseType, value)
|
||||||
let tmp: `t` = `value`
|
result = quote do: `t`(`parseStmt`)
|
||||||
tmp
|
|
||||||
|
|
||||||
elif t.typeKind == ntyRef:
|
elif t.typeKind == ntyRef:
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import std/[options, times, unittest]
|
||||||
|
|
||||||
|
import uuids
|
||||||
|
|
||||||
|
import fiber_orm/util
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
StringId = distinct string
|
||||||
|
NestedStringId = distinct StringId
|
||||||
|
UuidId = distinct UUID
|
||||||
|
Count = distinct int
|
||||||
|
Ratio = distinct float
|
||||||
|
Enabled = distinct bool
|
||||||
|
|
||||||
|
State = enum
|
||||||
|
pending
|
||||||
|
complete
|
||||||
|
|
||||||
|
DistinctState = distinct State
|
||||||
|
|
||||||
|
DistinctModel = object
|
||||||
|
id: StringId
|
||||||
|
nestedId: NestedStringId
|
||||||
|
userId: UuidId
|
||||||
|
count: Count
|
||||||
|
ratio: Ratio
|
||||||
|
enabled: Enabled
|
||||||
|
state: DistinctState
|
||||||
|
optionalId: Option[StringId]
|
||||||
|
absentId: Option[StringId]
|
||||||
|
relatedIds: seq[StringId]
|
||||||
|
occurredAt: DateTime
|
||||||
|
|
||||||
|
|
||||||
|
suite "distinct type row mapping":
|
||||||
|
|
||||||
|
test "parses each distinct type through its backing type":
|
||||||
|
let model = rowToModel(DistinctModel, @[
|
||||||
|
"item_123",
|
||||||
|
"nested_123",
|
||||||
|
"07e268ed-a3c1-4952-bc45-778b3000b76c",
|
||||||
|
"42",
|
||||||
|
"1.25",
|
||||||
|
"true",
|
||||||
|
"complete",
|
||||||
|
"optional_123",
|
||||||
|
"",
|
||||||
|
"{related_1,related_2}",
|
||||||
|
"2026-08-26 14:32:10.123457+00",
|
||||||
|
])
|
||||||
|
|
||||||
|
check:
|
||||||
|
string(model.id) == "item_123"
|
||||||
|
string(StringId(model.nestedId)) == "nested_123"
|
||||||
|
UUID(model.userId) ==
|
||||||
|
parseUUID("07e268ed-a3c1-4952-bc45-778b3000b76c")
|
||||||
|
int(model.count) == 42
|
||||||
|
float(model.ratio) == 1.25
|
||||||
|
bool(model.enabled)
|
||||||
|
State(model.state) == complete
|
||||||
|
model.optionalId.isSome
|
||||||
|
string(model.optionalId.get) == "optional_123"
|
||||||
|
model.absentId.isNone
|
||||||
|
model.relatedIds.len == 2
|
||||||
|
string(model.relatedIds[0]) == "related_1"
|
||||||
|
string(model.relatedIds[1]) == "related_2"
|
||||||
|
model.occurredAt.nanosecond == 123_457_000
|
||||||
|
|
||||||
|
test "preserves backing-type parse failures":
|
||||||
|
expect ValueError:
|
||||||
|
discard rowToModel(DistinctModel, @[
|
||||||
|
"item_123",
|
||||||
|
"nested_123",
|
||||||
|
"not-a-uuid",
|
||||||
|
"42",
|
||||||
|
"1.25",
|
||||||
|
"true",
|
||||||
|
"complete",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"{}",
|
||||||
|
"2026-08-26 14:32:10+00",
|
||||||
|
])
|
||||||
Reference in New Issue
Block a user