From f2f3b2d11c3b5a85fa2a03eec851bbf9bd715689 Mon Sep 17 00:00:00 2001 From: exfly Date: Fri, 13 Jun 2025 15:52:13 +0800 Subject: [PATCH] fix: pgbouncer https://github.com/lib/pq/pull/759/ --- .github/workflows/test.yml | 18 +----------- conn.go | 60 ++++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef1d4e38..1ff2bbdf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,7 @@ jobs: fail-fast: false matrix: postgres: + - '14' - '13' - '12' - '11' @@ -190,20 +191,3 @@ jobs: run: | PQTEST_BINARY_PARAMETERS=no go test -race -v ./... PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... - - - name: install goimports - run: go get golang.org/x/tools/cmd/goimports - - - name: install staticcheck - run: | - wget https://github.com/dominikh/go-tools/releases/latest/download/staticcheck_linux_amd64.tar.gz -O - | tar -xz staticcheck - - - name: run goimports - run: | - goimports -d -e . | awk '{ print } END { exit NR == 0 ? 0 : 1 }' - - - name: run staticcheck - run: ./staticcheck/staticcheck -go 1.13 ./... - - - name: build - run: go build -v . diff --git a/conn.go b/conn.go index da4ff9de..6c7a4f8c 100644 --- a/conn.go +++ b/conn.go @@ -828,6 +828,7 @@ func decideColumnFormats( } func (cn *conn) prepareTo(q, stmtName string) *stmt { + var err error st := &stmt{cn: cn, name: stmtName} b := cn.writeBuf('P') @@ -839,13 +840,29 @@ func (cn *conn) prepareTo(q, stmtName string) *stmt { b.byte('S') b.string(st.name) - b.next('S') + if stmtName != "" { + b.next('S') // sync + } else { + b.next('H') // flush + } cn.send(b) - cn.readParseResponse() - st.paramTyps, st.colNames, st.colTyps = cn.readStatementDescribeResponse() + if err := cn.readParseResponse(); err != nil { + cn.send(cn.writeBuf('S')) // sync + cn.readReadyForQuery() + panic(err) + } + + st.paramTyps, st.colNames, st.colTyps, err = cn.readStatementDescribeResponse() + if err != nil { + cn.send(cn.writeBuf('S')) // sync + cn.readReadyForQuery() + panic(err) + } st.colFmts, st.colFmtData = decideColumnFormats(st.colTyps, cn.disablePreparedBinaryResult) - cn.readReadyForQuery() + if stmtName != "" { + cn.readReadyForQuery() + } return st } @@ -906,7 +923,11 @@ func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) { if cn.binaryParameters { cn.sendBinaryModeQuery(query, args) - cn.readParseResponse() + if err := cn.readParseResponse(); err != nil { + cn.readReadyForQuery() + panic(err) + } + cn.readBindResponse() rows := &rows{cn: cn} rows.rowsHeader = cn.readPortalDescribeResponse() @@ -939,7 +960,10 @@ func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err if cn.binaryParameters { cn.sendBinaryModeQuery(query, args) - cn.readParseResponse() + if err := cn.readParseResponse(); err != nil { + cn.readReadyForQuery() + panic(err) + } cn.readBindResponse() cn.readPortalDescribeResponse() cn.postExecuteWorkaround() @@ -1819,25 +1843,25 @@ func (cn *conn) processBackendKeyData(r *readBuf) { cn.secretKey = r.int32() } -func (cn *conn) readParseResponse() { +func (cn *conn) readParseResponse() (err error) { t, r := cn.recv1() switch t { case '1': - return case 'E': - err := parseError(r) - cn.readReadyForQuery() - panic(err) + err = parseError(r) default: cn.err.set(driver.ErrBadConn) - errorf("unexpected Parse response %q", t) + err = fmterrorf("unexpected Parse response %q", t) } + + return } func (cn *conn) readStatementDescribeResponse() ( paramTyps []oid.Oid, colNames []string, colTyps []fieldDesc, + err error, ) { for { t, r := cn.recv1() @@ -1849,17 +1873,17 @@ func (cn *conn) readStatementDescribeResponse() ( paramTyps[i] = r.oid() } case 'n': - return paramTyps, nil, nil + return case 'T': colNames, colTyps = parseStatementRowDescribe(r) - return paramTyps, colNames, colTyps + return case 'E': - err := parseError(r) - cn.readReadyForQuery() - panic(err) + err = parseError(r) + return default: cn.err.set(driver.ErrBadConn) - errorf("unexpected Describe statement response %q", t) + err = fmterrorf("unexpected Describe statement response %q", t) + return } } }