From 100a8506e00299bc2cd9db31a3b46f1537bbd6d8 Mon Sep 17 00:00:00 2001 From: sm Date: Fri, 7 Oct 2022 10:34:41 +0200 Subject: [PATCH] release 0.108.3 --- Makefile | 3 ++ RELEASENOTES.md | 5 ++ driver/connection.go | 89 ++++++++++++-------------------- driver/driver.go | 2 +- driver/unicode/cesu8/encoding.go | 1 - go.mod | 8 +-- go.sum | 15 +++--- 7 files changed, 53 insertions(+), 70 deletions(-) diff --git a/Makefile b/Makefile index f650855d..c4e059aa 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,9 @@ # builds and tests project via go tools all: + @echo "update dependencies" + go get -u ./... + go mod tidy @echo "build and test" go build -v ./... go vet ./... diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6f50714f..e0055505 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -3,6 +3,11 @@ Release Notes ## Release 0.108 +Release 0.108.3 (upgrade urgency: low) + +- Error handling improvement (https://github.com/SAP/go-hdb/pull/95) +- Some minor source code cleanups + Release 0.108.2 (upgrade urgency: high) - Fixed hdb version parsing error using HANA v1 diff --git a/driver/connection.go b/driver/connection.go index 8c7218ad..78bd17bc 100644 --- a/driver/connection.go +++ b/driver/connection.go @@ -104,13 +104,9 @@ var ( // dbConn wraps the database tcp connection. It sets timeouts and handles driver ErrBadConn behavior. type dbConn struct { - // atomic access - alignment - cancelled int32 - metrics *metrics - conn net.Conn - timeout time.Duration - lastError error // error bad connection - closed bool + metrics *metrics + conn net.Conn + timeout time.Duration } func (c *dbConn) deadline() (deadline time.Time) { @@ -120,28 +116,10 @@ func (c *dbConn) deadline() (deadline time.Time) { return time.Now().Add(c.timeout) } -var ( - errCancelled = errors.New("db connection is canceled") - errClosed = errors.New("db connection is closed") -) - -func (c *dbConn) cancel() { - atomic.StoreInt32(&c.cancelled, 1) - c.lastError = errCancelled -} - -func (c *dbConn) close() error { - c.closed = true - c.lastError = errClosed - return c.conn.Close() -} +func (c *dbConn) close() error { return c.conn.Close() } // Read implements the io.Reader interface. func (c *dbConn) Read(b []byte) (n int, err error) { - // check if killed - if atomic.LoadInt32(&c.cancelled) == 1 { - return 0, driver.ErrBadConn - } var start time.Time //set timeout if err = c.conn.SetReadDeadline(c.deadline()); err != nil { @@ -156,16 +134,12 @@ func (c *dbConn) Read(b []byte) (n int, err error) { } retError: dlog.Printf("Connection read error local address %s remote address %s: %s", c.conn.LocalAddr(), c.conn.RemoteAddr(), err) - c.lastError = err - return n, driver.ErrBadConn + // wrap error in driver.ErrBadConn + return n, fmt.Errorf("%w: %s", driver.ErrBadConn, err) } // Write implements the io.Writer interface. func (c *dbConn) Write(b []byte) (n int, err error) { - // check if killed - if atomic.LoadInt32(&c.cancelled) == 1 { - return 0, driver.ErrBadConn - } var start time.Time //set timeout if err = c.conn.SetWriteDeadline(c.deadline()); err != nil { @@ -180,8 +154,8 @@ func (c *dbConn) Write(b []byte) (n int, err error) { } retError: dlog.Printf("Connection write error local address %s remote address %s: %s", c.conn.LocalAddr(), c.conn.RemoteAddr(), err) - c.lastError = err - return n, driver.ErrBadConn + // wrap error in driver.ErrBadConn + return n, fmt.Errorf("%w: %s", driver.ErrBadConn, err) } const ( @@ -238,6 +212,8 @@ const ( choStmtExec ) +var errCancelled = fmt.Errorf("%w: %s", driver.ErrBadConn, errors.New("db call cancelled")) + // Conn enhances a connection with go-hdb specific connection functions. type Conn interface { HDBVersion() *Version @@ -394,18 +370,17 @@ func (c *conn) versionString() (version string) { return } +/* +A better option would be to wrap driver.ErrBadConn directly into a fatal error (instead of using e.ErrFatal). +Then we could get rid of the isBad check executed on next 'roundrip' completely. +But unfortunately go database/sql does not return the original error in any case but returns driver.ErrBadConn in some cases instead. +Tested go versions wrapping driver.ErrBadConn instead of e.ErrFatal: +- go 1.17.13: works ok +- go 1.18.5 : does not work +- go 1.19.2 : does not work +*/ func (c *conn) isBad() bool { - switch { - - case c.dbConn.lastError != nil: - return true - - case c.lastError != nil: - if errors.Is(c.lastError, e.ErrFatal) { - return true - } - } - return false + return errors.Is(c.lastError, driver.ErrBadConn) || errors.Is(c.lastError, e.ErrFatal) } func (c *conn) pinger(d time.Duration, done <-chan struct{}) { @@ -446,7 +421,7 @@ func (c *conn) Ping(ctx context.Context) (err error) { select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return ctx.Err() case <-done: c.lastError = err @@ -520,7 +495,7 @@ func (c *conn) PrepareContext(ctx context.Context, query string) (stmt driver.St select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: c.metrics.chMsg <- gaugeMsg{idx: gaugeStmt, v: 1} // increment number of statements. @@ -587,7 +562,7 @@ func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (tx driver.Tx select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: c.metrics.chMsg <- gaugeMsg{idx: gaugeTx, v: 1} // increment number of transactions. @@ -652,7 +627,7 @@ func (c *conn) QueryContext(ctx context.Context, query string, nvargs []driver.N select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: if onCloser, ok := rows.(onCloser); ok { @@ -700,7 +675,7 @@ func (c *conn) ExecContext(ctx context.Context, query string, nvargs []driver.Na select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: c.lastError = err @@ -745,7 +720,7 @@ func (c *conn) DBConnectInfo(ctx context.Context, databaseName string) (ci *DBCo select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: c.lastError = err @@ -943,7 +918,7 @@ func (s *stmt) QueryContext(ctx context.Context, nvargs []driver.NamedValue) (ro select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: if onCloser, ok := rows.(onCloser); ok { @@ -1007,7 +982,7 @@ func (s *stmt) exec(ctx context.Context, nvargs []driver.NamedValue) (r driver.R select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: c.lastError = err @@ -1247,12 +1222,12 @@ func (s *callStmt) Close() error { c.lock() defer c.unlock() + s.conn.metrics.chMsg <- gaugeMsg{idx: gaugeStmt, v: -1} // decrement number of statements. + if c.isBad() { return driver.ErrBadConn } - s.conn.metrics.chMsg <- gaugeMsg{idx: gaugeStmt, v: -1} // decrement number of statements. - return c._dropStatementID(s.pr.stmtID) } @@ -1290,7 +1265,7 @@ func (s *callStmt) QueryContext(ctx context.Context, nvargs []driver.NamedValue) select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: if onCloser, ok := rows.(onCloser); ok { @@ -1330,7 +1305,7 @@ func (s *callStmt) ExecContext(ctx context.Context, nvargs []driver.NamedValue) select { case <-ctx.Done(): - c.dbConn.cancel() + c.lastError = errCancelled return nil, ctx.Err() case <-done: c.lastError = err diff --git a/driver/driver.go b/driver/driver.go index 10174e58..04b4bfc3 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -14,7 +14,7 @@ import ( ) // DriverVersion is the version number of the hdb driver. -const DriverVersion = "0.108.2" +const DriverVersion = "0.108.3" // DriverName is the driver name to use with sql.Open for hdb databases. const DriverName = "hdb" diff --git a/driver/unicode/cesu8/encoding.go b/driver/unicode/cesu8/encoding.go index 56c5c261..3b248793 100644 --- a/driver/unicode/cesu8/encoding.go +++ b/driver/unicode/cesu8/encoding.go @@ -12,7 +12,6 @@ import ( "unicode/utf8" "github.com/SAP/go-hdb/driver/internal/errors" - "golang.org/x/text/transform" ) diff --git a/go.mod b/go.mod index 276a4ed8..8ea940f3 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.19 require ( github.com/prometheus/client_golang v1.13.0 - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d - golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75 + golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b + golang.org/x/exp v0.0.0-20221006183845-316c7553db56 golang.org/x/text v0.3.7 ) @@ -13,10 +13,10 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 // indirect google.golang.org/protobuf v1.28.1 // indirect ) diff --git a/go.sum b/go.sum index 811db32e..197254ed 100644 --- a/go.sum +++ b/go.sum @@ -142,8 +142,9 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= +github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -203,8 +204,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0= +golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -215,8 +216,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75 h1:x03zeu7B2B11ySp+daztnwM5oBJ/8wGUSqrwcw9L0RA= -golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20221006183845-316c7553db56 h1:BrYbdKcCNjLyrN6aKqXy4hPw9qGI8IATkj4EWv9Q+kQ= +golang.org/x/exp v0.0.0-20221006183845-316c7553db56/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -322,8 +323,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 h1:AzgQNqF+FKwyQ5LbVrVqOcuuFB67N47F9+htZYH0wFM= +golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=