Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 8 additions & 49 deletions async_postgres/pg_client.nim
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,6 @@ template queryRecvLoop(
cachedColOids: seq[int32],
qr: var QueryResult,
timeout: Duration = ZeroDuration,
reuseBuffer: bool = true,
) =
var queryError: ref PgQueryError

Expand All @@ -391,19 +390,8 @@ template queryRecvLoop(
for i in 0 ..< qr.fields.len:
qr.fields[i].formatCode = cachedColFmts[i]
if qr.fields.len > 0:
if reuseBuffer:
if conn.rowDataBuf != nil:
conn.rowDataBuf = conn.rowDataBuf.reuseRowData(
int16(qr.fields.len), cachedColFmts, cachedColOids
)
else:
conn.rowDataBuf =
newRowData(int16(qr.fields.len), cachedColFmts, cachedColOids)
conn.rowDataBuf.fields = qr.fields
qr.data = conn.rowDataBuf
else:
qr.data = newRowData(int16(qr.fields.len), cachedColFmts, cachedColOids)
qr.data.fields = qr.fields
qr.data = newRowData(int16(qr.fields.len), cachedColFmts, cachedColOids)
qr.data.fields = qr.fields

block recvLoop:
while true:
Expand Down Expand Up @@ -433,17 +421,8 @@ template queryRecvLoop(
cf[i] = resultFormats[i]
else:
qr.fields = msg.fields
if reuseBuffer:
if conn.rowDataBuf != nil:
conn.rowDataBuf =
conn.rowDataBuf.reuseRowData(int16(qr.fields.len), cf, co)
else:
conn.rowDataBuf = newRowData(int16(qr.fields.len), cf, co)
conn.rowDataBuf.fields = qr.fields
qr.data = conn.rowDataBuf
else:
qr.data = newRowData(int16(qr.fields.len), cf, co)
qr.data.fields = qr.fields
qr.data = newRowData(int16(qr.fields.len), cf, co)
qr.data.fields = qr.fields
of bmkNoData:
discard
of bmkCommandComplete:
Expand Down Expand Up @@ -530,18 +509,8 @@ proc queryImpl(

var qr = QueryResult()
queryRecvLoop(
conn,
sql,
effectiveResultFormats,
cacheHit,
cacheMiss,
stmtName,
cachedFields,
cachedColFmts,
cachedColOids,
qr,
timeout,
reuseBuffer = false,
conn, sql, effectiveResultFormats, cacheHit, cacheMiss, stmtName, cachedFields,
cachedColFmts, cachedColOids, qr, timeout,
)
return qr

Expand Down Expand Up @@ -601,18 +570,8 @@ proc queryImpl(

var qr = QueryResult()
queryRecvLoop(
conn,
sql,
effectiveResultFormats,
cacheHit,
cacheMiss,
stmtName,
cachedFields,
cachedColFmts,
cachedColOids,
qr,
timeout,
reuseBuffer = false,
conn, sql, effectiveResultFormats, cacheHit, cacheMiss, stmtName, cachedFields,
cachedColFmts, cachedColOids, qr, timeout,
)
return qr

Expand Down
2 changes: 0 additions & 2 deletions async_postgres/pg_connection.nim
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ type
stmtCacheLru: DoublyLinkedList[string] ## LRU order: oldest at head, newest at tail
stmtCounter*: int
stmtCacheCapacity*: int ## 0=disabled, default 256
rowDataBuf*: RowData ## Reusable RowData buffer to avoid per-query allocation
hstoreOid*: int32 ## Dynamic OID for hstore extension type; 0 if not available
tracer*: PgTracer ## Inherited from ConnConfig on connect

Expand Down Expand Up @@ -1542,7 +1541,6 @@ proc reconnectInPlace(conn: PgConnection) {.async.} =
conn.recvBuf.setLen(0)
conn.recvBufStart = 0
conn.clearStmtCache()
conn.rowDataBuf = nil
conn.state = csConnecting
var newConn: PgConnection
try:
Expand Down
1 change: 0 additions & 1 deletion async_postgres/pg_pool.nim
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ proc resetSession*(pool: PgPool, conn: PgConnection) {.async.} =
try:
discard await conn.simpleExec(pool.config.resetQuery)
conn.clearStmtCache()
conn.rowDataBuf = nil
except CatchableError:
try:
await conn.close()
Expand Down
15 changes: 15 additions & 0 deletions tests/test_e2e.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6039,6 +6039,21 @@ suite "E2E: queryDirect / execDirect":

waitFor t()

test "queryDirect Row survives subsequent queries (lifetime bug)":
proc t() {.async.} =
let conn = await connect(plainConfig())
let qr1 = await conn.queryDirect("SELECT $1::text", "x")
let qr2 = await conn.queryDirect("SELECT $1::text", "y")
doAssert qr1.rowCount == 1
doAssert qr2.rowCount == 1
let row1 = Row(data: qr1.data, rowIdx: 0)
let row2 = Row(data: qr2.data, rowIdx: 0)
doAssert row1.getStr(0) == "x", "qr1 data was invalidated by qr2"
doAssert row2.getStr(0) == "y"
await conn.close()

waitFor t()

test "execDirect INSERT and UPDATE":
proc t() {.async.} =
let conn = await connect(plainConfig())
Expand Down
Loading