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..c70f86e 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/linxGnu/mssqlx 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..dd7f094 100644 --- a/go.sum +++ b/go.sum @@ -4,13 +4,14 @@ 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/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= +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/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..4d6b153 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,16 @@ 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") - } + var num int + 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")) + 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 {