lpil / lpil/pog

rows_as_map context lost in transaction connection

Open
#69 8 comments 1 reaction 0 assignees View on GitHub
Dominant language
Gleam
Stars
264
Forks
35
PR merge metrics
No merged PRs in 30d

Description

Hello!

Since upgrading pog to version 4, I am seeing some unexpected behavior with the feature to parse rows as a map when inside a transaction. My application, which was working with pog version 3, has started to fail because my decoders that are in transactions no longer have access to map data.

I have included a minimal reproduction. Note that the connection is instantiated with `rows_as_map(True)` which behaves as expected in a normal query on the connection itself, but that it reverts to tuple access when inside a transaction.

Maybe I'm holding it wrong? But since this seems to have been working before, maybe it's worth creating an issue.

```gleam
import gleam/dynamic/decode
import gleam/erlang/process
import gleam/io
import gleam/result
import gleam/string
import pog

pub fn main() -> Nil {
let db = init()

let assert Ok(rows) =
"
SELECT * FROM test
"
|> pog.query()
|> pog.returning({
use id <- decode.field("id", decode.int)
use name <- decode.field("name", decode.string)
decode.success(#(id, name))
})
|> pog.execute(db)

io.println("Rows: " <> rows |> string.inspect())

let _ =
pog.transaction(db, fn(tx) {
let assert Ok(rows) =
"
SELECT * FROM test
"
|> pog.query()
|> pog.returning({
// this works, but it should not because i set rows_as_map on the connection
let id = decode.at([0], decode.int)
let name = decode.at([1], decode.string)
decode.success(#(id, name))
})
|> pog.execute(tx)

io.println(
"THIS WILL PRINT but it shouldn't rows: " <> rows |> string.inspect(),
)
Ok(rows)
})

let _ =
pog.transaction(db, fn(tx) {
let assert Ok(rows) =
"
SELECT * FROM test
"
|> pog.query()
|> pog.returning({
// this fails, because the rows_as_map is not being applied in the transaction
use id <- decode.field("id", decode.int)
use name <- decode.field("name", decode.string)
decode.success(#(id, name))
})
|> pog.execute(tx)

io.println("THIS WILL NOT PRINT TX rows: " <> rows |> string.inspect())
Ok(rows)
})

Nil
}

fn init() {
let name = process.new_name("db_pog_test")
let assert Ok(started) =
name
|> pog.url_config("postgresql://pog_test:pog_test@localhost:5434/pog_test")
|> result.unwrap(pog.default_config(name))
|> pog.rows_as_map(True)
|> pog.start()

let db = started.data

let assert Ok(_) =
"
CREATE TABLE IF NOT EXISTS test (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
"
|> pog.query()
|> pog.execute(db)

let assert Ok(_) =
"
INSERT INTO test(name) VALUES ('pog_test');
"
|> pog.query()
|> pog.execute(db)

db
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the provided minimal reproduction in the issue, focusing on rows_as_map(True), pog.transaction, and the two pog.execute calls. Compare row decoding on the connection with decoding inside the transaction; done means the transactional query preserves map-shaped rows so decode.field works as shown.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.