Эх сурвалжийг харах

完成db operations封装

yjp 1 жил өмнө
parent
commit
e4c42b4d96

+ 73 - 0
db_operations/db.go

@@ -0,0 +1,73 @@
+package db_operations
+
+import (
+	"errors"
+	"fmt"
+	"gorm.io/driver/postgres"
+	"gorm.io/gorm"
+	"gorm.io/gorm/logger"
+)
+
+const (
+	databaseTypePostgres = "postgres"
+)
+
+type DBConfig struct {
+	Type               string `mapstructure:"type"`
+	UserName           string `mapstructure:"user_name"`
+	Password           string `mapstructure:"password"`
+	Address            string `mapstructure:"address"`
+	Port               string `mapstructure:"port"`
+	Database           string `mapstructure:"database"`
+	MaxConnections     int    `mapstructure:"max_connections"`
+	MaxIdleConnections int    `mapstructure:"max_idle_connections"`
+}
+
+func newGormDB(dbConfig *DBConfig) (*gorm.DB, error) {
+	if dbConfig == nil {
+		return nil, errors.New("没有传递数据库配置")
+	}
+
+	var gormDB *gorm.DB
+
+	switch dbConfig.Type {
+	case databaseTypePostgres:
+		innerGormDB, err := newPostgresSQLOperationsItem(dbConfig)
+		if err != nil {
+			return nil, err
+		}
+
+		gormDB = innerGormDB
+	default:
+		innerGormDB, err := newPostgresSQLOperationsItem(dbConfig)
+		if err != nil {
+			return nil, err
+		}
+
+		gormDB = innerGormDB
+	}
+
+	return gormDB, nil
+}
+
+func newPostgresSQLOperationsItem(dbConfig *DBConfig) (*gorm.DB, error) {
+	dsn := "host=%s port=%s user=%s password=%s dbname=%s sslmode=disable TimeZone=Asia/Shanghai"
+	connStr := fmt.Sprintf(dsn, dbConfig.Address, dbConfig.Port, dbConfig.UserName, dbConfig.Password, dbConfig.Database)
+	return gorm.Open(postgres.Open(connStr), &gorm.Config{
+		Logger:      logger.Default.LogMode(logger.Info),
+		PrepareStmt: true,
+	})
+}
+
+func destroyGormDB(gormDB *gorm.DB) error {
+	if gormDB == nil {
+		return nil
+	}
+
+	db, err := gormDB.DB()
+	if err != nil {
+		return err
+	}
+
+	return db.Close()
+}

+ 46 - 0
db_operations/db_operations.go

@@ -0,0 +1,46 @@
+package db_operations
+
+type DBOperations interface {
+	BeginTransaction() TransactionDBOperations
+	BaseDBOperations
+}
+
+type TransactionDBOperations interface {
+	BaseDBOperations
+	RollbackTransaction()
+	CommitTransaction()
+}
+
+type BaseDBOperations interface {
+	// 会重置数据库连接的方法
+	NewSession() DBOperations
+	Table(name string, args ...any) DBOperations
+	Raw(sql string, values ...any) DBOperations
+
+	// 组织SQL语句相关的方法
+	Select(query string, args ...any) DBOperations
+	Where(query string, args ...any) DBOperations
+	Or(query string, args ...any) DBOperations
+	GroupBy(groupBy string) DBOperations
+	OrderBy(orderBy string) DBOperations
+	Joins(query string, args ...any) DBOperations
+	Having(query string, args ...any) DBOperations
+	Paging(pageNo int, pageSize int) DBOperations
+
+	// 写方法
+	Create(model interface{}) error
+	Delete(idModel interface{}) error
+	Updates(idModel interface{}, updateData map[string]any) error
+	UpdatesWithRowsAffected(idModel interface{}, updateData map[string]any) (int64, error)
+
+	// 使用Model的查询方法
+	Query(models interface{}, pageNo int, pageSize int) error
+	QueryOne(model interface{}) error
+
+	// 不使用Model的查询方法,需要结合Table或者Raw使用,如需分页,需要配合Paging
+	Row() (map[string]any, error)
+	Rows() ([]map[string]any, error)
+
+	// 其他方法
+	Count(count *int64) error
+}

+ 9 - 0
db_operations/dberr/dberr.go

@@ -0,0 +1,9 @@
+package dberr
+
+import "errors"
+
+var (
+	ErrDBOperationsNotExist = errors.New("数据库操作不存在")
+	ErrDBRecordHasExist     = errors.New("记录已存在")
+	ErrDBRecordNotExist     = errors.New("记录不存在")
+)

+ 296 - 0
db_operations/operations.go

@@ -0,0 +1,296 @@
+package db_operations
+
+import (
+	"database/sql"
+	"errors"
+	"git.sxidc.com/service-supports/ds-sdk/db_operations/dberr"
+	"git.sxidc.com/service-supports/fslog"
+	"github.com/mitchellh/mapstructure"
+	"gorm.io/gorm"
+	"strings"
+	"time"
+)
+
+type TransactionOperations struct {
+	Operations
+}
+
+func (op *TransactionOperations) RollbackTransaction() {
+	defer func() {
+		op.processDB = op.initDB
+	}()
+
+	op.processDB.Rollback()
+}
+
+func (op *TransactionOperations) CommitTransaction() {
+	defer func() {
+		op.processDB = op.initDB
+	}()
+
+	op.processDB.Commit()
+}
+
+type Operations struct {
+	initDB       *gorm.DB
+	processDB    *gorm.DB
+	stopPingChan chan any
+}
+
+func NewOperationsFromMap(configMap map[string]any) (*Operations, error) {
+	dbConfig := new(DBConfig)
+	err := mapstructure.Decode(configMap, dbConfig)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewOperations(dbConfig)
+}
+
+func NewOperations(dbConfig *DBConfig) (*Operations, error) {
+	gormDB, err := newGormDB(dbConfig)
+	if err != nil {
+		return nil, err
+	}
+
+	sqlDB, err := gormDB.DB()
+	if err != nil {
+		return nil, err
+	}
+
+	if dbConfig.MaxConnections == 0 {
+		dbConfig.MaxConnections = 50
+	}
+
+	if dbConfig.MaxIdleConnections == 0 {
+		dbConfig.MaxIdleConnections = 10
+	}
+
+	sqlDB.SetMaxOpenConns(dbConfig.MaxConnections)
+	sqlDB.SetMaxIdleConns(dbConfig.MaxIdleConnections)
+
+	op := &Operations{
+		initDB:       gormDB,
+		processDB:    gormDB,
+		stopPingChan: make(chan any),
+	}
+
+	op.startBeatHeart(sqlDB)
+
+	return op, nil
+}
+
+func DestroyOperation(op *Operations) error {
+	if op == nil {
+		return nil
+	}
+
+	if op.initDB == nil {
+		return nil
+	}
+
+	op.stopBeatHeart()
+
+	return destroyGormDB(op.initDB)
+}
+
+func (op *Operations) startBeatHeart(sqlDB *sql.DB) {
+	go func() {
+		pingTicker := time.NewTicker(time.Minute * 1)
+		defer pingTicker.Stop()
+
+		for {
+			select {
+			case <-op.stopPingChan:
+				return
+			case <-pingTicker.C:
+				err := sqlDB.Ping()
+				if err != nil {
+					fslog.Error(err)
+				}
+			}
+		}
+	}()
+}
+
+func (op *Operations) stopBeatHeart() {
+	if op.stopPingChan != nil {
+		close(op.stopPingChan)
+		op.stopPingChan = nil
+	}
+}
+
+func (op *Operations) BeginTransaction() TransactionDBOperations {
+	tx := op.initDB.Begin()
+	return &TransactionOperations{
+		Operations{
+			initDB:    tx,
+			processDB: tx,
+		},
+	}
+}
+
+func (op *Operations) NewSession() DBOperations {
+	return &Operations{
+		initDB:    op.initDB,
+		processDB: op.initDB,
+	}
+}
+
+func (op *Operations) Table(name string, args ...any) DBOperations {
+	op.processDB = op.initDB.Table(name, args...)
+	return op
+}
+
+func (op *Operations) Raw(sql string, values ...any) DBOperations {
+	op.processDB = op.initDB.Raw(sql, values...)
+	return op
+}
+
+func (op *Operations) Select(query string, args ...any) DBOperations {
+	op.processDB = op.processDB.Select(query, args...)
+	return op
+}
+
+func (op *Operations) Where(query string, args ...any) DBOperations {
+	op.processDB = op.processDB.Where(query, args...)
+	return op
+}
+
+func (op *Operations) Or(query string, args ...any) DBOperations {
+	op.processDB = op.processDB.Or(query, args...)
+	return op
+}
+
+func (op *Operations) GroupBy(groupBy string) DBOperations {
+	op.processDB = op.processDB.Group(groupBy)
+	return op
+}
+
+func (op *Operations) OrderBy(orderBy string) DBOperations {
+	op.processDB = op.processDB.Order(orderBy)
+	return op
+}
+
+func (op *Operations) Joins(query string, args ...any) DBOperations {
+	op.processDB = op.processDB.Joins(query, args...)
+	return op
+}
+
+func (op *Operations) Having(query string, args ...any) DBOperations {
+	op.processDB = op.processDB.Having(query, args...)
+	return op
+}
+
+func (op *Operations) Paging(pageNo int, pageSize int) DBOperations {
+	if pageNo != 0 && pageSize != 0 {
+		offset := -1
+
+		if pageNo == -1 || pageSize == -1 {
+			offset = -1
+			pageSize = -1
+		} else {
+			offset = (pageNo - 1) * pageSize
+		}
+
+		op.processDB = op.processDB.Offset(offset).Limit(pageSize)
+	}
+
+	return op
+}
+
+func (op *Operations) Create(model interface{}) error {
+	err := op.processDB.Create(model).Error
+	if err != nil {
+		if strings.Contains(err.Error(), "SQLSTATE 23505") {
+			return dberr.ErrDBRecordHasExist
+		}
+
+		return err
+	}
+
+	return nil
+}
+
+func (op *Operations) Delete(idModel interface{}) error {
+	return op.processDB.Delete(idModel).Error
+}
+
+func (op *Operations) Updates(idModel interface{}, updateData map[string]any) error {
+	err := op.processDB.Model(idModel).Updates(updateData).Error
+	if err != nil {
+		if strings.Contains(err.Error(), "SQLSTATE 23505") {
+			return dberr.ErrDBRecordHasExist
+		}
+
+		return err
+	}
+
+	return nil
+}
+
+func (op *Operations) UpdatesWithRowsAffected(idModel interface{}, updateData map[string]any) (int64, error) {
+	op.processDB = op.processDB.Model(idModel).Updates(updateData)
+	if op.processDB.Error != nil {
+		return 0, op.processDB.Error
+	}
+
+	return op.processDB.RowsAffected, nil
+}
+
+func (op *Operations) Query(models interface{}, pageNo int, pageSize int) error {
+	if pageNo != 0 && pageSize != 0 {
+		offset := (pageNo - 1) * pageSize
+		op.processDB = op.processDB.Offset(offset).Limit(pageSize)
+	}
+
+	err := op.processDB.Find(models).Error
+	if err != nil {
+		return err
+	}
+
+	op.processDB = op.processDB.Offset(-1).Limit(-1)
+
+	return nil
+}
+
+func (op *Operations) QueryOne(model interface{}) error {
+	err := op.processDB.First(model).Error
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return dberr.ErrDBRecordNotExist
+		}
+
+		return err
+	}
+
+	return nil
+}
+
+func (op *Operations) Row() (map[string]any, error) {
+	valueMap := make(map[string]any)
+	err := op.processDB.Scan(&valueMap).Error
+	if err != nil {
+		return nil, err
+	}
+
+	if valueMap == nil || len(valueMap) == 0 {
+		return nil, dberr.ErrDBRecordNotExist
+	}
+
+	return valueMap, nil
+}
+
+func (op *Operations) Rows() ([]map[string]any, error) {
+	valueMaps := make([]map[string]any, 0)
+	err := op.processDB.Scan(&valueMaps).Error
+	if err != nil {
+		return nil, err
+	}
+
+	return valueMaps, nil
+}
+
+func (op *Operations) Count(count *int64) error {
+	return op.processDB.Count(count).Error
+}

+ 9 - 1
go.mod

@@ -5,10 +5,12 @@ go 1.22.0
 require (
 	git.sxidc.com/go-tools/api_binding v1.3.23
 	git.sxidc.com/go-tools/utils v1.5.1
+	git.sxidc.com/service-supports/fserr v0.3.2
+	gorm.io/driver/postgres v1.5.7
+	gorm.io/gorm v1.25.9
 )
 
 require (
-	git.sxidc.com/service-supports/fserr v0.3.2 // indirect
 	git.sxidc.com/service-supports/fslog v0.5.9 // indirect
 	git.sxidc.com/service-supports/websocket v1.3.1 // indirect
 	github.com/bytedance/sonic v1.10.0 // indirect
@@ -23,6 +25,11 @@ require (
 	github.com/go-resty/resty/v2 v2.11.0 // indirect
 	github.com/goccy/go-json v0.10.2 // indirect
 	github.com/gorilla/websocket v1.5.0 // indirect
+	github.com/jackc/pgpassfile v1.0.0 // indirect
+	github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
+	github.com/jackc/pgx/v5 v5.4.3 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/jinzhu/now v1.1.5 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.5 // indirect
 	github.com/leodido/go-urn v1.2.4 // indirect
@@ -32,6 +39,7 @@ require (
 	github.com/olahol/melody v1.1.1 // indirect
 	github.com/pelletier/go-toml/v2 v2.1.0 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
+	github.com/rogpeppe/go-internal v1.12.0 // indirect
 	github.com/satori/go.uuid v1.2.0 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	github.com/ugorji/go/codec v1.2.11 // indirect

+ 22 - 1
go.sum

@@ -47,12 +47,26 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
 github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
+github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
+github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
+github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
 github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
 github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
 github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
 github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
@@ -70,6 +84,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 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/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
 github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -151,12 +167,17 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
 google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
+gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
+gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
+gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
 nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 11 - 0
sdk/db_operations.go

@@ -0,0 +1,11 @@
+package sdk
+
+import "git.sxidc.com/service-supports/ds-sdk/db_operations"
+
+func NewDBOperations(dbConfig *db_operations.DBConfig) (db_operations.DBOperations, error) {
+	return db_operations.NewOperations(dbConfig)
+}
+
+func DestroyDBOperations(dbOps db_operations.DBOperations) error {
+	return db_operations.DestroyOperation(dbOps.(*db_operations.Operations))
+}

+ 13 - 2
sdk/instance.go

@@ -2,6 +2,7 @@ package sdk
 
 import (
 	"git.sxidc.com/service-supports/ds-sdk/client"
+	"git.sxidc.com/service-supports/ds-sdk/db_operations"
 	"strings"
 )
 
@@ -39,9 +40,15 @@ func InitInstance(token string, baseUrl string, namespace string, dataSource *Da
 		return err
 	}
 
+	dbOperations, err := initDBOperations(options.dataSource.Spec)
+	if err != nil {
+		return err
+	}
+
 	sdkInstance = &SDK{
-		options: options,
-		client:  c,
+		options:      options,
+		client:       c,
+		dbOperations: dbOperations,
 	}
 
 	return nil
@@ -84,3 +91,7 @@ func initDataSource(c *client.Client, options *Options) error {
 
 	return nil
 }
+
+func initDBOperations(dataSourceSpec map[string]any) (db_operations.DBOperations, error) {
+	return db_operations.NewOperationsFromMap(dataSourceSpec)
+}

+ 8 - 2
sdk/sdk.go

@@ -4,11 +4,17 @@ import (
 	"errors"
 	"git.sxidc.com/go-tools/utils/strutils"
 	"git.sxidc.com/service-supports/ds-sdk/client"
+	"git.sxidc.com/service-supports/ds-sdk/db_operations"
 )
 
 type SDK struct {
-	options *Options
-	client  *client.Client
+	options      *Options
+	client       *client.Client
+	dbOperations db_operations.DBOperations
+}
+
+func (s *SDK) GetDBOperations() db_operations.DBOperations {
+	return s.dbOperations
 }
 
 func (s *SDK) CreateDataContainer(name string, spec map[string]any) error {