postgres-nio icon indicating copy to clipboard operation
postgres-nio copied to clipboard

Decoding "1.0" as Double fails

Open finestructure opened this issue 3 years ago • 2 comments

I'm running into a PostgresNIO.PostgresDecodingError error 1 when decoding the value 1.0 from the query SELECT 1.0. In order to make the decoding work, I need to rewrite the query as SELECT 1.0::float.

The slight issue is that I'll have quite a number of queries from another source and it will be tedious to have to modify all of them, in particular as they might get changed upstream in the future.

For instance, the same decoding error appears when trying to run and decode the following query:

SELECT
'index hit rate' AS name,
(sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) AS ratio
FROM pg_statio_user_indexes
UNION ALL
SELECT
'table hit rate' AS name,
sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) AS ratio
FROM pg_statio_user_tables

Here's a little snippet I used for testing to reduce the error:

        do {
            print("SELECT 1.0")
            let rows = try await conn.query(.init(stringLiteral: "SELECT 1.0"), logger: logger)
            for try await r in rows.decode(Double.self, context: .default) {
                print("r: \(r)")
            }
        } catch {
            print(error.localizedDescription)
        }

        do {
            print("SELECT 1.0::float")
            let rows = try await conn.query(.init(stringLiteral: "SELECT 1.0::float"), logger: logger)
            for try await r in rows.decode(Double.self, context: .default) {
                print("r: \(r)")
            }
        } catch {
            print(error.localizedDescription)
        }

This prints

SELECT 1.0
The operation couldn’t be completed. (PostgresNIO.PostgresDecodingError error 1.)
SELECT 1.0::float
r: 1.0

Is there any way to decode the double/float without having to modify the original SQL? (I did try to decode Float.self, no luck.)

This is PostgresNIO 1.10.0

finestructure avatar May 20 '22 17:05 finestructure

Oh, I see: looking through the code I see that I need to use Foundation's Decimal to decode this:

            let rows = try await conn.query(.init(stringLiteral: "SELECT 1.0"), logger: logger)
            for try await r in rows.decode(Decimal.self, context: .default) {
                print("r: \(r)")
            }

Sorry for the noise! (Although this might be a good example to add to the README as might be a common stumbling block.)

finestructure avatar May 21 '22 03:05 finestructure

This should work with Double as well. I'll investigate. Thanks for opening the issue @finestructure

fabianfett avatar May 21 '22 12:05 fabianfett