Why is 1 and 0 are returned as string?

With the following:
isUsed: sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`
isUsed: sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`
I get isUsed as "1" or "0" whereas I would expect a boolean.
19 Replies
binajmen
binajmen11mo ago
I tried ... then cast(1 as bit) else ... or with tinyint, but I get the error: syntax error at position 294 near 'tinyint'
Angelelz
Angelelz11mo ago
You get "1" or "0" because you are type casting, but not changing the type returned from the database at runtime. I suggest you use .mapWith() to runtime map your query to what you want:
isUsed: sql`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(Boolean)
isUsed: sql`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(Boolean)
binajmen
binajmen11mo ago
But I thought 1 should be at least an integer Why a string in the end result? I understand I'm only type casting, but even with sql<number>... I receive a string ("1" or "0") I did find out mapWith and I'm using as follow:
sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(
(value) => value === "1",
),
sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(
(value) => value === "1",
),
Because Boolean will always return true on a non empty string What I don't understand is why the end result is a string, whereas it should be at least a number Oo
Angelelz
Angelelz11mo ago
When you use the sql magic operator, drizzle does not have any information of the type that the database/driver will return. It will just put whatever the db returned through the driver in your isUsed key
binajmen
binajmen11mo ago
If I run the equivalent query in a MySQL client, I get a number 1 or 0.
Angelelz
Angelelz11mo ago
Depending on your dialect, you could cast it a db level with:
sql<boolean>`case when ${usedExchanges.data} is not null then cast(1 as signed) else cast(0 as signed) end`
sql<boolean>`case when ${usedExchanges.data} is not null then cast(1 as signed) else cast(0 as signed) end`
binajmen
binajmen11mo ago
Yup that's what I would expect. In this case the db returns integer. Yet drizzle provides me string. It seems there's an inconvenient conversion made by Drizzle. At least, that's how it looks like
Angelelz
Angelelz11mo ago
Drizzle is returning the value without any transformation, this is somehting mysql2 driver does unfortunately Same happens with for example count(*)
binajmen
binajmen11mo ago
I already tried cast(1 as signed) and still get a string I probably mispoke, maybe it is as the mysql2 driver
Angelelz
Angelelz11mo ago
What about:
sql<boolean>`cast(case when ${usedExchanges.data} is not null then 1 else 0 end as signed)`
sql<boolean>`cast(case when ${usedExchanges.data} is not null then 1 else 0 end as signed)`
binajmen
binajmen11mo ago
anyhow, I wonder if this could be considered as a bug, since it's not a 1 to 1 result compared to the pure SQL let me try still the same 🙈
Angelelz
Angelelz11mo ago
It is not a bug IMO. It's just a design decision by mysql2 driver. Maybe they're trying to avoid loosing precision with stuff like bigint, IDK
binajmen
binajmen11mo ago
mmh ok, I'll move on with .mapWith then. I'll dig in parallel the reason, cause I feel this is wrong, if not a bug 🙂 thanks for the sparring session 🙏
Angelelz
Angelelz11mo ago
GitHub
API incompatibility re aggregate functions sum and avg return strin...
SELECT SUM(amt), AVG(amt) FROM MYTABLE; mysqljs returns numeric columns but mysql2 returns strings.
Angelelz
Angelelz11mo ago
Just to give you an example But I think I read a parameter you can pass, might be worth trying
Angelelz
Angelelz11mo ago
GitHub
API incompatibility re aggregate functions sum and avg return strin...
SELECT SUM(amt), AVG(amt) FROM MYTABLE; mysqljs returns numeric columns but mysql2 returns strings.
Angelelz
Angelelz11mo ago
I'm not saying this is your issue, but just an example
binajmen
binajmen11mo ago
At least it seems to support your suggestion that it is a deliberate choice I think .mapWith is the right trade-off here 🙂
Angelelz
Angelelz11mo ago
glad I could help
Want results from more Discord servers?
Add your server