pgx
pgx copied to clipboard
unexpected pipeline result: *pgconn.PipelineSync
Describe the bug
When usign a batch to insert an object I've got following error: unexpected pipeline result: *pgconn.PipelineSync
To Reproduce Steps to reproduce the behavior:
I've failed to reproduce
Expected behavior Error message will tell what's the problem is.
Actual behavior Error message that looks like internal pgx issue.
Version
- Go: go1.20.4 linux/amd64
- pgx: v5.5.0
Additional context Add any other context about the problem here.
In case somebody encounters this issue, on pgx v.5.5.5, the error was triggered by calling batchReq.Exec() after sending a batch update (or insert).
Example:
var b pgx.Batch
sql := `UPDATE table SET field = $1 WHERE other=$2`
for x,y := range stuff {
b.Queue(sql, x, y)
}
batchReq := c.conn.SendBatch(ctx, &b)
defer func() {
err = batchReqClose(err, batchReq)
}()
_, err := batchReq.Exec()
return err
Removing _, err := batchReq.Exec() fixed the issue for me.
However I'll note that this issue doesn't always happen, not sure what is triggering condition but I have a service with that code that never triggers the *pgconn.PipelineSync error, while another service will suddenly start getting it. If anyone has an idea as to what can cause the behaviour that'd be interesting to know.
I've been able to get this to reproduce reliably when the update batch is of 0 queries.
Yes, that sounds silly on the surface, but sometimes there's nothing where you'd normally expect something, when you're getting your data programmatically.
Our solution for this was to check that the Batch's .Len() != 0 before calling Exec, but depending on where you're getting your data, you may be able to determine that there's nothing sooner.
@LiruMouse
Do you have an example of this?
I just created a simple test that sent a batch with 0 queries and it didn't crash.
batch := &pgx.Batch{}
br := conn.SendBatch(ctx, batch)
err := br.Close()
require.NoError(t, err)
Interesting, @jackc, I'll try to paraphrase and summarize our code to demonstrate (please endure any semantic errors, though)
We're taking rows from another database, which has a simple iterator interface.
So please assume that query_from_row builds proper queries based on the data in row_iter, and calls batch.Queue on that query, with the necessary data from the row.
batch := &pgx.Batch{}
for row_iter.Next() {
queue_query_from_row(row_iter, &batch) // batch.Queue
}
br := conn.SendBatch(ctx, batch)
defer br.Close()
tag, err := br.Exec()
Is it that call to Exec?
@LiruMouse
So, trying to read more results than queries were included in the batch? That's probably a bug in the application. I've added some additional checks to return a better error message in dced53f79657fa287825038ea606e696a72d5dd2. But I don't think this is a pgx bug.
@LiruMouse
So, trying to read more results than queries were included in the batch? That's probably a bug in the application. I've added some additional checks to return a better error message in dced53f. But I don't think this is a pgx bug.
I completely agree, this is a bug in the application, where the end developer expects there to be more data available to create queries, but in certain cases that is not so.
Thanks for improving the error, that should help users understand this particular problem in the future.