From c2b8ca843e4794b35f0f7ed879d08004a4ab9749 Mon Sep 17 00:00:00 2001 From: linxGnu Date: Tue, 6 Jul 2021 15:34:42 +0900 Subject: [PATCH 1/4] [BreakChanges] Update QueryRow* APIs --- balancer.go | 4 --- go.mod | 8 ++++-- go.sum | 6 ++++ mssqlx.go | 76 ++++++++++++++++++++------------------------------ mssqlx_test.go | 51 +++++++++++++-------------------- types.go | 8 ------ 6 files changed, 62 insertions(+), 91 deletions(-) diff --git a/balancer.go b/balancer.go index 5eb33bb..49db813 100644 --- a/balancer.go +++ b/balancer.go @@ -46,10 +46,6 @@ func newBalancer(ctx context.Context, numHealthChecker int, numDbInstance int, i return c } -func (c *balancer) size() int { - return c.dbs.size() -} - func (c *balancer) getHealthCheckPeriod() uint64 { return atomic.LoadUint64(&c.healthCheckPeriod) } diff --git a/go.mod b/go.mod index bdbc77e..61d914d 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,13 @@ module github.com/linxGnu/mssqlx +go 1.16 + require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-sql-driver/mysql v1.6.0 - github.com/jmoiron/sqlx v1.3.2-0.20210128211550-a1d5e6473423 - github.com/lib/pq v1.10.0 - github.com/mattn/go-sqlite3 v1.14.6 + github.com/jmoiron/sqlx v1.3.4 + github.com/lib/pq v1.10.2 + github.com/mattn/go-sqlite3 v1.14.7 github.com/stretchr/testify v1.7.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 1e65577..e1cb787 100644 --- a/go.sum +++ b/go.sum @@ -6,11 +6,17 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/jmoiron/sqlx v1.3.2-0.20210128211550-a1d5e6473423 h1:5dW2FAtvUgEOn6kHCOW0ldbcFVEHDdjRlpdps/5HSLI= github.com/jmoiron/sqlx v1.3.2-0.20210128211550-a1d5e6473423/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= +github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= +github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/mssqlx.go b/mssqlx.go index 1057ac2..5ceb267 100644 --- a/mssqlx.go +++ b/mssqlx.go @@ -13,13 +13,13 @@ import ( var ( // ErrNetwork networking error - ErrNetwork = errors.New("Network error/Connection refused") + ErrNetwork = errors.New("network error/connection refused") // ErrNoConnection there is no connection to db - ErrNoConnection = errors.New("No connection available") + ErrNoConnection = errors.New("no connection available") // ErrNoConnectionOrWsrep there is no connection to db or Wsrep is not ready - ErrNoConnectionOrWsrep = errors.New("No connection available or Wsrep is not ready") + ErrNoConnectionOrWsrep = errors.New("no connection available or Wsrep is not ready") ) const ( @@ -761,93 +761,79 @@ func (dbs *DBs) QueryxContextOnMaster(ctx context.Context, query string, args .. return } -func _queryRow(ctx context.Context, target *balancer, query string, args ...interface{}) (dbr *wrapper, res *sql.Row, err error) { - var w *wrapper - - if w, err = getDBFromBalancer(target); err != nil { - reportError(query, err) - } else { - res, dbr = w.db.QueryRowContext(ctx, query, args...), w +func (dbs *DBs) _queryRow(ctx context.Context, target *balancer, query string, args ...interface{}) *sql.Row { + w, err := getDBFromBalancer(target) + if err != nil { + // no available node -> pick one + w = dbs._all[0] } - - return + return w.db.QueryRowContext(ctx, query, args...) } // QueryRow executes a query on slaves that is expected to return at most one row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRow(query string, args ...interface{}) (r *sql.Row, err error) { - _, r, err = _queryRow(context.Background(), dbs.readBalancer(), query, args...) - return +func (dbs *DBs) QueryRow(query string, args ...interface{}) *sql.Row { + return dbs._queryRow(context.Background(), dbs.readBalancer(), query, args...) } // QueryRowOnMaster executes a query on masters that is expected to return at most one row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRowOnMaster(query string, args ...interface{}) (r *sql.Row, err error) { - _, r, err = _queryRow(context.Background(), dbs.masters, query, args...) - return +func (dbs *DBs) QueryRowOnMaster(query string, args ...interface{}) *sql.Row { + return dbs._queryRow(context.Background(), dbs.masters, query, args...) } // QueryRowContext executes a query on slaves that is expected to return at most one row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRowContext(ctx context.Context, query string, args ...interface{}) (r *sql.Row, err error) { - _, r, err = _queryRow(ctx, dbs.readBalancer(), query, args...) - return +func (dbs *DBs) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { + return dbs._queryRow(ctx, dbs.readBalancer(), query, args...) } // QueryRowContextOnMaster executes a query on masters that is expected to return at most one row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRowContextOnMaster(ctx context.Context, query string, args ...interface{}) (r *sql.Row, err error) { - _, r, err = _queryRow(ctx, dbs.masters, query, args...) - return +func (dbs *DBs) QueryRowContextOnMaster(ctx context.Context, query string, args ...interface{}) *sql.Row { + return dbs._queryRow(ctx, dbs.masters, query, args...) } -func _queryRowx(ctx context.Context, target *balancer, query string, args ...interface{}) (dbr *wrapper, res *sqlx.Row, err error) { - var w *wrapper - - if w, err = getDBFromBalancer(target); err != nil { - reportError(query, err) - } else { - res, dbr = w.db.QueryRowxContext(ctx, query, args...), w +func (dbs *DBs) _queryRowx(ctx context.Context, target *balancer, query string, args ...interface{}) *sqlx.Row { + w, err := getDBFromBalancer(target) + if err != nil { + // no available node -> pick one + w = dbs._all[0] } - - return + return w.db.QueryRowxContext(ctx, query, args...) } // QueryRowx executes a query on slaves that is expected to return at most one row. // But return sqlx.Row instead of sql.Row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRowx(query string, args ...interface{}) (r *sqlx.Row, err error) { - _, r, err = _queryRowx(context.Background(), dbs.readBalancer(), query, args...) - return +func (dbs *DBs) QueryRowx(query string, args ...interface{}) *sqlx.Row { + return dbs._queryRowx(context.Background(), dbs.readBalancer(), query, args...) } // QueryRowxOnMaster executes a query on masters that is expected to return at most one row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRowxOnMaster(query string, args ...interface{}) (r *sqlx.Row, err error) { - _, r, err = _queryRowx(context.Background(), dbs.masters, query, args...) - return +func (dbs *DBs) QueryRowxOnMaster(query string, args ...interface{}) *sqlx.Row { + return dbs._queryRowx(context.Background(), dbs.masters, query, args...) } // QueryRowxContext executes a query on slaves that is expected to return at most one row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRowxContext(ctx context.Context, query string, args ...interface{}) (r *sqlx.Row, err error) { - _, r, err = _queryRowx(ctx, dbs.readBalancer(), query, args...) - return +func (dbs *DBs) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *sqlx.Row { + return dbs._queryRowx(ctx, dbs.readBalancer(), query, args...) } // QueryRowxContextOnMaster executes a query on masters that is expected to return at most one row. // QueryRow always returns a non-nil value. Errors are deferred until // Row's Scan method is called. -func (dbs *DBs) QueryRowxContextOnMaster(ctx context.Context, query string, args ...interface{}) (r *sqlx.Row, err error) { - _, r, err = _queryRowx(ctx, dbs.masters, query, args...) - return +func (dbs *DBs) QueryRowxContextOnMaster(ctx context.Context, query string, args ...interface{}) *sqlx.Row { + return dbs._queryRowx(ctx, dbs.masters, query, args...) } func _select(ctx context.Context, target *balancer, dest interface{}, query string, args ...interface{}) (dbr *wrapper, err error) { diff --git a/mssqlx_test.go b/mssqlx_test.go index d6ac7d5..028af94 100644 --- a/mssqlx_test.go +++ b/mssqlx_test.go @@ -287,6 +287,18 @@ func TestParseError(t *testing.T) { } } +func (c *balancer) size() int { + return c.dbs.size() +} + +func (b *dbList) size() (v int) { + list, stored := b.list.Load().([]*wrapper) + if stored { + v = len(list) + } + return +} + func TestDbBalancer(t *testing.T) { dbB := newBalancer(context.Background(), 0, 4, true) @@ -942,37 +954,14 @@ func TestNilReceivers(t *testing.T) { t.Error("Expected error when getting into nil struct ptr.") } - if _, err = db.QueryRow("SELECT * FROM person LIMIT 1"); err != nil { - t.Error("Fail query row") - } - - if r, err := db.QueryRowOnMaster("SELECT * FROM person LIMIT 2"); err != nil || r == nil { - t.Error("Fail query row") - } - - if _, err = db.QueryRowContext(context.Background(), "SELECT * FROM person LIMIT 1"); err != nil { - t.Error("Fail query row") - } - - if r, err := db.QueryRowContextOnMaster(context.Background(), "SELECT * FROM person LIMIT 2"); err != nil || r == nil { - t.Error("Fail query row") - } - - if _, err = db.QueryRowx("SELECT * FROM person LIMIT 1"); err != nil { - t.Error("Fail query row") - } - - if r, err := db.QueryRowxOnMaster("SELECT * FROM person LIMIT 2"); err != nil || r == nil { - t.Error("Fail query row") - } - - if _, err = db.QueryRowxContext(context.Background(), "SELECT * FROM person LIMIT 1"); err != nil { - t.Error("Fail query row") - } - - if r, err := db.QueryRowxContextOnMaster(context.Background(), "SELECT * FROM person LIMIT 2"); err != nil || r == nil { - t.Error("Fail query row") - } + require.NotNil(t, db.QueryRow("SELECT * FROM person LIMIT 1")) + require.NotNil(t, db.QueryRowOnMaster("SELECT * FROM person LIMIT 2")) + require.NotNil(t, db.QueryRowContext(context.Background(), "SELECT * FROM person LIMIT 1")) + require.NotNil(t, db.QueryRowContextOnMaster(context.Background(), "SELECT * FROM person LIMIT 2")) + require.NotNil(t, db.QueryRowx("SELECT * FROM person LIMIT 1")) + require.NotNil(t, db.QueryRowxOnMaster("SELECT * FROM person LIMIT 2")) + require.NotNil(t, db.QueryRowxContext(context.Background(), "SELECT * FROM person LIMIT 1")) + require.NotNil(t, db.QueryRowxContextOnMaster(context.Background(), "SELECT * FROM person LIMIT 2")) var pp *[]Person if err = db.Select(pp, "SELECT * FROM person"); err == nil { diff --git a/types.go b/types.go index bf5f43d..7235e31 100644 --- a/types.go +++ b/types.go @@ -48,14 +48,6 @@ type dbList struct { _ [9]uint64 } -func (b *dbList) size() (v int) { - list, stored := b.list.Load().([]*wrapper) - if stored { - v = len(list) - } - return -} - func (b *dbList) current() (w *wrapper) { list, stored := b.list.Load().([]*wrapper) if stored { From 47e9608643d492a97734918a5f437a84c2fa824e Mon Sep 17 00:00:00 2001 From: linxGnu Date: Tue, 6 Jul 2021 15:40:29 +0900 Subject: [PATCH 2/4] Update test --- mssqlx_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mssqlx_test.go b/mssqlx_test.go index 028af94..a885bc5 100644 --- a/mssqlx_test.go +++ b/mssqlx_test.go @@ -954,7 +954,9 @@ func TestNilReceivers(t *testing.T) { t.Error("Expected error when getting into nil struct ptr.") } - require.NotNil(t, db.QueryRow("SELECT * FROM person LIMIT 1")) + var num int + require.NotNil(t, db.QueryRow("SELECT count(1) FROM person").Scan(&num)) + require.True(t, num > 0) require.NotNil(t, db.QueryRowOnMaster("SELECT * FROM person LIMIT 2")) require.NotNil(t, db.QueryRowContext(context.Background(), "SELECT * FROM person LIMIT 1")) require.NotNil(t, db.QueryRowContextOnMaster(context.Background(), "SELECT * FROM person LIMIT 2")) From 54b7d9b3e8d94bb377cab803f292995e5221ce03 Mon Sep 17 00:00:00 2001 From: linxGnu Date: Tue, 6 Jul 2021 15:42:04 +0900 Subject: [PATCH 3/4] Update --- go.mod | 2 -- go.sum | 5 ----- 2 files changed, 7 deletions(-) diff --git a/go.mod b/go.mod index 61d914d..c70f86e 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,5 @@ module github.com/linxGnu/mssqlx -go 1.16 - require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index e1cb787..dd7f094 100644 --- a/go.sum +++ b/go.sum @@ -4,16 +4,11 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/jmoiron/sqlx v1.3.2-0.20210128211550-a1d5e6473423 h1:5dW2FAtvUgEOn6kHCOW0ldbcFVEHDdjRlpdps/5HSLI= -github.com/jmoiron/sqlx v1.3.2-0.20210128211550-a1d5e6473423/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= -github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= From c18b687bb5ababf221a837ebc61c7cc6fdc669c2 Mon Sep 17 00:00:00 2001 From: linxGnu Date: Tue, 6 Jul 2021 15:43:00 +0900 Subject: [PATCH 4/4] Update --- mssqlx_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mssqlx_test.go b/mssqlx_test.go index a885bc5..4d6b153 100644 --- a/mssqlx_test.go +++ b/mssqlx_test.go @@ -955,7 +955,7 @@ func TestNilReceivers(t *testing.T) { } var num int - require.NotNil(t, db.QueryRow("SELECT count(1) FROM person").Scan(&num)) + require.Nil(t, db.QueryRow("SELECT count(1) FROM person").Scan(&num)) require.True(t, num > 0) require.NotNil(t, db.QueryRowOnMaster("SELECT * FROM person LIMIT 2")) require.NotNil(t, db.QueryRowContext(context.Background(), "SELECT * FROM person LIMIT 1"))