Skip to content

Commit

Permalink
Add zdb package for Database Management
Browse files Browse the repository at this point in the history
* Add zdatabase pkg

* Add clickhouse db type

* Fix db port

* db tests and mocks

* go mod tidy fix

* update pkg/db readme
  • Loading branch information
lucaslopezf authored Aug 30, 2023
1 parent 3aa39dd commit 9e79ccd
Show file tree
Hide file tree
Showing 14 changed files with 1,745 additions and 3 deletions.
21 changes: 20 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,52 @@ require (
github.com/prometheus/client_golang v1.15.0
github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.1
github.com/stretchr/testify v1.8.2
go.uber.org/zap v1.24.0
golang.org/x/sync v0.1.0
gorm.io/driver/clickhouse v0.5.1
gorm.io/gorm v1.25.4
)

require (
github.com/ClickHouse/ch-go v0.53.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.8.3 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-faster/city v1.0.1 // indirect
github.com/go-faster/errors v0.6.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.16.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/paulmach/orb v0.9.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sys v0.7.0 // indirect
Expand Down
1,114 changes: 1,112 additions & 2 deletions go.sum

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions pkg/zdb/methods.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package zdb

import (
"database/sql"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)

func wrap(db *gorm.DB) ZDatabase {
return &zDatabase{db}
}

func (z *zDatabase) GetDbConnection() *gorm.DB {
return z.db
}

func (z *zDatabase) Exec(query string, values ...interface{}) ZDatabase {
return wrap(z.db.Exec(query, values...))
}

func (z *zDatabase) Find(out interface{}, where ...interface{}) ZDatabase {
return wrap(z.db.Find(out, where...))
}

func (z *zDatabase) Scan(dest interface{}) ZDatabase {
return wrap(z.db.Scan(dest))
}

func (z *zDatabase) Row() *sql.Row {
return z.db.Row()
}

func (z *zDatabase) Rows() (*sql.Rows, error) {
return z.db.Rows()
}

func (z *zDatabase) ScanRows(rows *sql.Rows, result interface{}) error {
return z.db.ScanRows(rows, result)
}

func (z *zDatabase) Create(value interface{}) ZDatabase {
return wrap(z.db.Create(value))
}

func (z *zDatabase) Delete(value interface{}, where ...interface{}) ZDatabase {
return wrap(z.db.Delete(value, where...))
}

func (z *zDatabase) Raw(sql string, values ...interface{}) ZDatabase {
return wrap(z.db.Raw(sql, values...))
}

func (z *zDatabase) Table(name string) ZDatabase {
return wrap(z.db.Table(name))
}

func (z *zDatabase) Clauses(conds ...clause.Expression) ZDatabase {
return wrap(z.db.Clauses(conds...))
}

func (z *zDatabase) Transaction(fc func(tx ZDatabase) error, opts ...*sql.TxOptions) (err error) {
return z.db.Transaction(func(tx *gorm.DB) error {
return fc(wrap(tx))
}, opts...)
}

func (z *zDatabase) RowsAffected() int64 {
return z.db.RowsAffected
}

func (z *zDatabase) Error() error {
return z.db.Error
}
116 changes: 116 additions & 0 deletions pkg/zdb/methods_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package zdb

import (
"database/sql"
"github.com/stretchr/testify/mock"
"testing"

"github.com/stretchr/testify/suite"
"gorm.io/gorm/clause"
)

type TestStruct struct {
Name string
Age int
}

type ZDatabaseSuite struct {
suite.Suite
db ZDatabase
}

func (suite *ZDatabaseSuite) SetupTest() {
mockDb := new(MockZDatabase)
suite.db = mockDb
}

func (suite *ZDatabaseSuite) TestFind() {
suite.db.(*MockZDatabase).On("Find", &TestStruct{}, "Name = ?", "Messi").Return(suite.db)
newDb := suite.db.Find(&TestStruct{}, "Name = ?", "Messi")
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestScan() {
suite.db.(*MockZDatabase).On("Scan", &TestStruct{}).Return(suite.db)
newDb := suite.db.Scan(&TestStruct{})
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestRows() {
mockRows := new(sql.Rows)
suite.db.(*MockZDatabase).On("Rows").Return(mockRows, nil)
rows, err := suite.db.Rows()
suite.Nil(err)
suite.Equal(mockRows, rows)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestScanRows() {
mockRows := new(sql.Rows)
suite.db.(*MockZDatabase).On("ScanRows", mockRows, &TestStruct{}).Return(nil)
err := suite.db.ScanRows(mockRows, &TestStruct{})
suite.Nil(err)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestCreate() {
suite.db.(*MockZDatabase).On("Create", &TestStruct{}).Return(suite.db)
newDb := suite.db.Create(&TestStruct{})
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestDelete() {
suite.db.(*MockZDatabase).On("Delete", &TestStruct{}, "Name = ?", "Messi").Return(suite.db)
newDb := suite.db.Delete(&TestStruct{}, "Name = ?", "Messi")
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestRaw() {
suite.db.(*MockZDatabase).On("Raw", "SELECT * FROM tests WHERE name = ?", "Messi").Return(suite.db)
newDb := suite.db.Raw("SELECT * FROM tests WHERE name = ?", "Messi")
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestExec() {
suite.db.(*MockZDatabase).On("Exec", "UPDATE test SET name = ?", []interface{}{"Messi"}).Return(suite.db)
newDb := suite.db.Exec("UPDATE test SET name = ?", "Messi")
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestTable() {
suite.db.(*MockZDatabase).On("Table", "test_table").Return(suite.db)
newDb := suite.db.Table("test_table")
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestClauses() {
suite.db.(*MockZDatabase).On("Clauses", mock.Anything).Return(suite.db)
newDb := suite.db.Clauses(clause.OnConflict{})
suite.NotNil(newDb)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestError() {
suite.db.(*MockZDatabase).On("Error").Return(nil)
err := suite.db.Error()
suite.Nil(err)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func (suite *ZDatabaseSuite) TestRowsAffected() {
suite.db.(*MockZDatabase).On("RowsAffected").Return(int64(1))
rows := suite.db.RowsAffected()
suite.Equal(int64(1), rows)
suite.db.(*MockZDatabase).AssertExpectations(suite.T())
}

func TestZDatabaseSuite(t *testing.T) {
suite.Run(t, new(ZDatabaseSuite))
}
104 changes: 104 additions & 0 deletions pkg/zdb/mock_zdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package zdb

import (
"database/sql"
"github.com/stretchr/testify/mock"
"github.com/zondax/golem/pkg/zdb/zdbconfig"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)

type MockZDatabase struct {
mock.Mock
}

func (m *MockZDatabase) GetDbConnection() *gorm.DB {
args := m.Called()
return args.Get(0).(*gorm.DB)
}

func (m *MockZDatabase) Find(dest interface{}, conds ...interface{}) ZDatabase {
args := m.Called(dest, conds[0], conds[1])
return args.Get(0).(ZDatabase)
}

func (m *MockZDatabase) Scan(dest interface{}) ZDatabase {
m.Called(dest)
return m
}

func (m *MockZDatabase) Rows() (*sql.Rows, error) {
args := m.Called()
return args.Get(0).(*sql.Rows), args.Error(1)
}

func (m *MockZDatabase) ScanRows(rows *sql.Rows, result interface{}) error {
args := m.Called(rows, result)
return args.Error(0)
}

func (m *MockZDatabase) Create(value interface{}) ZDatabase {
m.Called(value)
return m
}

func (m *MockZDatabase) Delete(value interface{}, conds ...interface{}) ZDatabase {
args := m.Called(value, conds[0], conds[1])
return args.Get(0).(ZDatabase)
}

func (m *MockZDatabase) Raw(sql string, values ...interface{}) ZDatabase {
args := m.Called(sql, values[0])
return args.Get(0).(ZDatabase)
}

func (m *MockZDatabase) Exec(sql string, values ...interface{}) ZDatabase {
m.Called(sql, values)
return m
}

func (m *MockZDatabase) Table(name string) ZDatabase {
m.Called(name)
return m
}

func (m *MockZDatabase) Transaction(fc func(tx ZDatabase) error, opts ...*sql.TxOptions) (err error) {
args := m.Called(fc, opts)
return args.Error(0)
}

func (m *MockZDatabase) Clauses(conds ...clause.Expression) ZDatabase {
args := m.Called(conds[0])
return args.Get(0).(ZDatabase)
}

func (m *MockZDatabase) Error() error {
args := m.Called()
return args.Error(0)
}

func (m *MockZDatabase) RowsAffected() int64 {
args := m.Called()
return args.Get(0).(int64)
}

// MockDBConnector

type MockDBConnector struct {
mock.Mock
}

func (m *MockDBConnector) NewInstance(dbType string, config *zdbconfig.Config) (ZDatabase, error) {
args := m.Called(dbType, config)
return args.Get(0).(ZDatabase), args.Error(1)
}

func (m *MockDBConnector) Connect(config *zdbconfig.Config) (*gorm.DB, error) {
args := m.Called(config)
return args.Get(0).(*gorm.DB), args.Error(1)
}

func (m *MockDBConnector) VerifyConnection(db *gorm.DB) error {
args := m.Called(db)
return args.Error(0)
}
Loading

0 comments on commit 9e79ccd

Please sign in to comment.