Skip to content
This repository was archived by the owner on Apr 15, 2025. It is now read-only.

Commit 56dfa7c

Browse files
fix(raw queries): correct None handling for all fields (#1000)
## Change Summary See #998. ## Agreement By submitting this pull request, I confirm that you can use, modify, copy and redistribute this contribution, under the terms of your choice. --------- Co-authored-by: Robert Craigie <robert@craigie.dev>
1 parent f1ab3b1 commit 56dfa7c

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

databases/sync_tests/types/raw_queries/test_bigint.py

+23
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,25 @@
99

1010
class Queries(BaseModel):
1111
select: LiteralString
12+
select_null: LiteralString
1213

1314

1415
_mysql_queries = Queries(
1516
select='SELECT * FROM Types WHERE `bigint` = ?',
17+
select_null='SELECT * FROM Types WHERE `optional_bigint` IS NULL',
1618
)
1719

1820
_postgresql_queries = Queries(
1921
select='SELECT * FROM "Types" WHERE bigint = $1',
22+
select_null='SELECT * FROM "Types" WHERE optional_bigint IS NULL',
2023
)
2124

2225
RAW_QUERIES: DatabaseMapping[Queries] = {
2326
'mysql': _mysql_queries,
2427
'mariadb': _mysql_queries,
2528
'sqlite': Queries(
2629
select='SELECT * FROM Types WHERE bigint = ?',
30+
select_null='SELECT * FROM Types WHERE optional_bigint IS NULL',
2731
),
2832
'postgresql': _postgresql_queries,
2933
'cockroachdb': _postgresql_queries,
@@ -47,3 +51,22 @@ def test_query_first(
4751
assert model is not None
4852
assert model.id == record.id
4953
assert model.bigint == 12522
54+
55+
56+
def test_query_first_optional(
57+
client: Prisma,
58+
database: SupportedDatabase,
59+
) -> None:
60+
"""Use of BigInt in raw SELECT queries with optional/nullable results"""
61+
queries = RAW_QUERIES[database]
62+
63+
record = client.types.create({'optional_bigint': None})
64+
65+
found = client.query_first(queries.select_null)
66+
assert found['id'] == record.id
67+
assert found['optional_bigint'] is None
68+
69+
model = client.query_first(queries.select_null, model=Types)
70+
assert model is not None
71+
assert model.id == record.id
72+
assert model.optional_bigint is None

databases/sync_tests/types/raw_queries/test_decimal.py

+23
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,25 @@
1111

1212
class Queries(BaseModel):
1313
select: LiteralString
14+
select_null: LiteralString
1415

1516

1617
_mysql_queries = Queries(
1718
select='SELECT * FROM Types WHERE decimal_ = ?',
19+
select_null='SELECT * FROM Types WHERE optional_decimal IS NULL',
1820
)
1921

2022
_postgresql_queries = Queries(
2123
select='SELECT * FROM "Types" WHERE decimal_ = $1::numeric',
24+
select_null='SELECT * FROM "Types" WHERE optional_decimal IS NULL',
2225
)
2326

2427
RAW_QUERIES: DatabaseMapping[Queries] = {
2528
'mysql': _mysql_queries,
2629
'mariadb': _mysql_queries,
2730
'sqlite': Queries(
2831
select='SELECT * FROM Types WHERE decimal_ = ?',
32+
select_null='SELECT * FROM Types WHERE optional_decimal IS NULL',
2933
),
3034
'postgresql': _postgresql_queries,
3135
'cockroachdb': _postgresql_queries,
@@ -55,3 +59,22 @@ def test_query_first(
5559
assert model is not None
5660
assert model.id == record2.id
5761
assert model.decimal_ == Decimal('1.24343336464224')
62+
63+
64+
def test_query_first_optional(
65+
client: Prisma,
66+
database: SupportedDatabase,
67+
) -> None:
68+
"""Use of decimal in raw SELECT queries with optional/nullable results"""
69+
queries = RAW_QUERIES[database]
70+
71+
record = client.types.create({'optional_decimal': None})
72+
73+
found = client.query_first(queries.select_null)
74+
assert found['id'] == record.id
75+
assert found['optional_decimal'] is None
76+
77+
model = client.query_first(queries.select_null, model=Types)
78+
assert model is not None
79+
assert model.id == record.id
80+
assert model.optional_decimal is None

databases/tests/types/raw_queries/test_bigint.py

+24
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,25 @@
1010

1111
class Queries(BaseModel):
1212
select: LiteralString
13+
select_null: LiteralString
1314

1415

1516
_mysql_queries = Queries(
1617
select='SELECT * FROM Types WHERE `bigint` = ?',
18+
select_null='SELECT * FROM Types WHERE `optional_bigint` IS NULL',
1719
)
1820

1921
_postgresql_queries = Queries(
2022
select='SELECT * FROM "Types" WHERE bigint = $1',
23+
select_null='SELECT * FROM "Types" WHERE optional_bigint IS NULL',
2124
)
2225

2326
RAW_QUERIES: DatabaseMapping[Queries] = {
2427
'mysql': _mysql_queries,
2528
'mariadb': _mysql_queries,
2629
'sqlite': Queries(
2730
select='SELECT * FROM Types WHERE bigint = ?',
31+
select_null='SELECT * FROM Types WHERE optional_bigint IS NULL',
2832
),
2933
'postgresql': _postgresql_queries,
3034
'cockroachdb': _postgresql_queries,
@@ -49,3 +53,23 @@ async def test_query_first(
4953
assert model is not None
5054
assert model.id == record.id
5155
assert model.bigint == 12522
56+
57+
58+
@pytest.mark.asyncio
59+
async def test_query_first_optional(
60+
client: Prisma,
61+
database: SupportedDatabase,
62+
) -> None:
63+
"""Use of BigInt in raw SELECT queries with optional/nullable results"""
64+
queries = RAW_QUERIES[database]
65+
66+
record = await client.types.create({'optional_bigint': None})
67+
68+
found = await client.query_first(queries.select_null)
69+
assert found['id'] == record.id
70+
assert found['optional_bigint'] is None
71+
72+
model = await client.query_first(queries.select_null, model=Types)
73+
assert model is not None
74+
assert model.id == record.id
75+
assert model.optional_bigint is None

databases/tests/types/raw_queries/test_decimal.py

+24
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,25 @@
1212

1313
class Queries(BaseModel):
1414
select: LiteralString
15+
select_null: LiteralString
1516

1617

1718
_mysql_queries = Queries(
1819
select='SELECT * FROM Types WHERE decimal_ = ?',
20+
select_null='SELECT * FROM Types WHERE optional_decimal IS NULL',
1921
)
2022

2123
_postgresql_queries = Queries(
2224
select='SELECT * FROM "Types" WHERE decimal_ = $1::numeric',
25+
select_null='SELECT * FROM "Types" WHERE optional_decimal IS NULL',
2326
)
2427

2528
RAW_QUERIES: DatabaseMapping[Queries] = {
2629
'mysql': _mysql_queries,
2730
'mariadb': _mysql_queries,
2831
'sqlite': Queries(
2932
select='SELECT * FROM Types WHERE decimal_ = ?',
33+
select_null='SELECT * FROM Types WHERE optional_decimal IS NULL',
3034
),
3135
'postgresql': _postgresql_queries,
3236
'cockroachdb': _postgresql_queries,
@@ -57,3 +61,23 @@ async def test_query_first(
5761
assert model is not None
5862
assert model.id == record2.id
5963
assert model.decimal_ == Decimal('1.24343336464224')
64+
65+
66+
@pytest.mark.asyncio
67+
async def test_query_first_optional(
68+
client: Prisma,
69+
database: SupportedDatabase,
70+
) -> None:
71+
"""Use of decimal in raw SELECT queries with optional/nullable results"""
72+
queries = RAW_QUERIES[database]
73+
74+
record = await client.types.create({'optional_decimal': None})
75+
76+
found = await client.query_first(queries.select_null)
77+
assert found['id'] == record.id
78+
assert found['optional_decimal'] is None
79+
80+
model = await client.query_first(queries.select_null, model=Types)
81+
assert model is not None
82+
assert model.id == record.id
83+
assert model.optional_decimal is None

src/prisma/_raw_query.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,11 @@ def _deserialize_prisma_object(
135135
key = result.columns[i]
136136
prisma_type = result.types[i]
137137

138-
if prisma_type.endswith('-array'):
139-
if field is None:
140-
# array fields can stil be `None`
141-
new_obj[key] = None
142-
continue
138+
if field is None:
139+
new_obj[key] = None
140+
continue
143141

142+
if prisma_type.endswith('-array'):
144143
if not isinstance(field, list):
145144
raise TypeError(
146145
f'Expected array data for {key} column with internal type {prisma_type}',

0 commit comments

Comments
 (0)