In my Postgres DB, I recently added the following calculated field value to the SELECT SQL query when users login:
SUM(m.file_size) AS byte_count
Because media.file_size
(aka m.file_size
) has an int8
data type, I naturally assumed that byte_count
would be returned with the same. But lo and behold, it was being returned as a string.
So I modified the SQL code like this:
SUM(m.file_size)::bigint AS byte_count
That still returned a string so I tried ::int8
but still a string. Then I tried:
CAST(SUM(m.file_size) AS bigint) AS byte_count
but still a string. So finally I tried this:
SUM(m.file_size)::int AS byte_count
This now returns a number (good!) but my fear is that as a user’s byte total climbs above the capacity of int
, that I’m going to run into problems. In fact, I put a very large number into a related max_bytes
field – 223372036854775808
and sure enough, got an "integer out of range" error.
Is there some other way to cast the calculated field as an 8 byte bigint
?
As per @Adrian Claver in the comments:
- I’m doing a
console.log
of the output from the server and can clearly see when the value is a number or a string. - I’m using ExpressJS for my server code.
- I’m running Postgres 14.4 on my MacBook
In my users
table is this field:
max_bytes int8
In my signInUser
function in my server code, is this calculated column:
COALESCE(SUM(m.file_size)::int, 0) AS byte_count
In my media
table is this field:
file_size int8
3
Answers
The current version of the SELECT statement includes the following:
which returns the following, in this example, as per a
console.log
:But then, if I change the aforementioned SQL code back to what it was before:
and changed the
max_bytes
value for this user to:922337203685477580
. Here's the resultTo move forward, I think I have no choice but to return
max_bytes
andbyte_count
as strings and then cast them as numbers on the client side.Hm, without seeing the definition of the table, it’s hard to confirm if the type actually is of type int8. I.E., if I make an assumption with a table design as follows:
And then I select the values and confirm their type like such:
We can observe the following results:
As you can see, the type of the calculated column is indeed int8, bigint being an alias for int8.
Even if I defined a column as a string and cast it within the calculated column (which I do not recommend doing, ever.) It still returns the accurate results:
So, can you confirm how your calculated column is declared in your table definition ? Obviously this is a simple example but, I can’t reproduce your results. It could potentially be with your calculated column definition and the types it’s using.
It’s important to note that the
pg_typeof()
function is returning the type of the data as stored in the table. However, after summing, it is converted to type numeric as documented in Postgres Documentationsum ( bigint ) → numeric
Functions Aggregate:To answer your question, which you technically already did, you can use the following methods to cast:
CAST ( value AS target_type )
orvalue::target_type
Just a quick follow-up and thank you to all that tried to help . . .
Not today, but soon I will upgrade my local Postgres from
v14.4
to the latestv17.2
. Maybe that will correct it.Today, I did upgrade ExpressJS on my server from
4.18.1
to4.21.2
.In the client code, I’m performing this on-the-fly conversion:
And indeed, the two values in question are correctly being converted from strings to numbers.
Once again, thank you all for your great help!