yjp 11 месяцев назад
Родитель
Сommit
2e9baffe09

+ 5 - 4
client/sql.go

@@ -18,7 +18,7 @@ const (
 )
 
 func (c *Client) ExecuteRawSql(token string, baseUrl string,
-	namespace string, dataSource string, sql string) ([]map[string]any, error) {
+	namespace string, dataSource string, sql string, executeParams map[string]any) ([]map[string]any, error) {
 	fullUrl, err := url.JoinPath(baseUrl, executeRawSqlUrl)
 	if err != nil {
 		return nil, err
@@ -30,9 +30,10 @@ func (c *Client) ExecuteRawSql(token string, baseUrl string,
 	})
 
 	err = c.post(token, fullUrl, map[string]any{
-		"namespace":  namespace,
-		"dataSource": dataSource,
-		"sql":        sql,
+		"namespace":     namespace,
+		"dataSource":    dataSource,
+		"sql":           sql,
+		"executeParams": executeParams,
 	}, resp)
 	if err != nil {
 		return nil, err

+ 43 - 7
demo/demo.go

@@ -3,15 +3,22 @@ package main
 import (
 	"git.sxidc.com/go-tools/utils/strutils"
 	"git.sxidc.com/service-supports/ds-sdk/sdk"
+	"math/rand"
 )
 
 const (
 	token         = "IpTTwAQweh/BP51fz5CzWKQFaXHvZe6ewvk6yOcAOkU="
-	baseUrl       = "http://localhost:10000"
+	address       = "localhost"
+	httpPort      = "10000"
+	grpcPort      = "10001"
 	namespace     = "ns-sdk-demo"
 	dataSource    = "ds-sdk-demo"
 	dataContainer = "dc-sdk-demo"
-	sql           = "delete-sdk-demo"
+	deleteSql     = "delete-sdk-demo"
+)
+
+const (
+	sqlInsertTpl = "INSERT INTO test.classes (id, name, student_num) VALUES ('[[ .id ]]', '[[ .name ]]', [[ .student_num ]])"
 )
 
 var (
@@ -46,9 +53,21 @@ var (
 )
 
 func main() {
-	classID1 := strutils.SimpleUUID()
+	classID := strutils.SimpleUUID()
+	className := strutils.SimpleUUID()
+	studentNum := rand.Int31n(100)
+
+	insertExecuteParams := map[string]any{
+		"id":          classID,
+		"name":        className,
+		"student_num": studentNum,
+	}
 
-	err := sdk.InitInstance(token, baseUrl, namespace, dataSource)
+	deleteExecuteParams := map[string]any{
+		"id": classID,
+	}
+
+	err := sdk.InitInstance(token, address, httpPort, grpcPort, namespace, dataSource)
 	if err != nil {
 		panic(err)
 	}
@@ -65,17 +84,34 @@ func main() {
 		panic(err)
 	}
 
-	err = sdk.GetInstance().CreateSQL(sql, sqlSpec.ToMap())
+	err = sdk.GetInstance().CreateSQL(deleteSql, sqlSpec.ToMap())
 	if err != nil {
 		panic(err)
 	}
 
-	_, err = sdk.GetInstance().ExecuteSql(sql, map[string]any{"id": classID1})
+	_, err = sdk.GetInstance().ExecuteRawSql(sqlInsertTpl, insertExecuteParams)
 	if err != nil {
 		panic(err)
 	}
 
-	err = sdk.GetInstance().DeleteSQL(sql)
+	_, err = sdk.GetInstance().ExecuteSql(deleteSql, deleteExecuteParams)
+	if err != nil {
+		panic(err)
+	}
+
+	err = sdk.GetInstance().Transaction(func(tx *sdk.Transaction) error {
+		err := tx.ExecuteRawSql(sqlInsertTpl, insertExecuteParams)
+		if err != nil {
+			return err
+		}
+
+		err = tx.ExecuteSql(deleteSql, deleteExecuteParams)
+		if err != nil {
+			return err
+		}
+
+		return nil
+	})
 	if err != nil {
 		panic(err)
 	}

+ 9 - 10
go.mod

@@ -5,15 +5,16 @@ 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/fslog v0.5.9
 	github.com/fatih/structs v1.1.0
-	github.com/mitchellh/mapstructure v1.5.0
-	gorm.io/driver/postgres v1.5.7
-	gorm.io/gorm v1.25.9
+	github.com/golang/protobuf v1.5.4
+	github.com/mwitkow/go-proto-validators v0.3.2
+	google.golang.org/grpc v1.63.2
+	google.golang.org/protobuf v1.33.0
 )
 
 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
 	github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
@@ -26,14 +27,11 @@ require (
 	github.com/go-playground/validator/v10 v10.15.3 // indirect
 	github.com/go-resty/resty/v2 v2.11.0 // indirect
 	github.com/goccy/go-json v0.10.2 // indirect
+	github.com/gogo/protobuf v1.3.0 // 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/kr/pretty v0.3.0 // indirect
 	github.com/leodido/go-urn v1.2.4 // indirect
 	github.com/mattn/go-isatty v0.0.19 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -52,7 +50,8 @@ require (
 	golang.org/x/net v0.21.0 // indirect
 	golang.org/x/sys v0.17.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
-	google.golang.org/protobuf v1.31.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
+	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 26 - 24
go.sum

@@ -20,6 +20,7 @@ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ
 github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
 github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
 github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -43,43 +44,43 @@ github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqx
 github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
 github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
 github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
+github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 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/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 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.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
 github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+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/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=
 github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
-github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mwitkow/go-proto-validators v0.3.2 h1:qRlmpTzm2pstMKKzTdvwPCF5QfBNURSlAgN/R+qbKos=
+github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w=
 github.com/olahol/melody v1.1.1 h1:amgBhR7pDY0rA0JHWprgLF0LnVztognAwEQgf/WYLVM=
 github.com/olahol/melody v1.1.1/go.mod h1:GgkTl6Y7yWj/HtfD48Q5vLKPVoZOH+Qqgfa7CvJgJM4=
 github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
@@ -88,6 +89,7 @@ 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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 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=
@@ -162,26 +164,26 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
 golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-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=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
+google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
+google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
+google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 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=

+ 60 - 0
grpc_client/grpc_client.go

@@ -0,0 +1,60 @@
+package grpc_client
+
+import (
+	"context"
+	"git.sxidc.com/service-supports/ds-sdk/grpc_client/v1"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
+	"time"
+)
+
+type Client struct {
+	conn         *grpc.ClientConn
+	sqlServiceV1 v1.SqlServiceClient
+	timeout      time.Duration
+}
+
+func NewClient(address string, timeout time.Duration) (*Client, error) {
+	conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	if err != nil {
+		return nil, err
+	}
+
+	return &Client{
+		conn:         conn,
+		sqlServiceV1: v1.NewSqlServiceClient(conn),
+		timeout:      timeout,
+	}, nil
+}
+
+func Destroy(c *Client) error {
+	if c == nil {
+		return nil
+	}
+
+	err := c.conn.Close()
+	if err != nil {
+		return err
+	}
+
+	c.sqlServiceV1 = nil
+	c.conn = nil
+	c = nil
+
+	return nil
+}
+
+func (c *Client) Transaction() (v1.SqlService_TransactionClient, error) {
+	var ctx context.Context
+
+	if c.timeout == 0 {
+		ctx = context.Background()
+	} else {
+		timeoutCtx, cancel := context.WithTimeout(context.Background(), c.timeout)
+		defer cancel()
+
+		ctx = timeoutCtx
+	}
+
+	return c.sqlServiceV1.Transaction(ctx)
+}

+ 525 - 0
grpc_client/v1/request/sql.pb.go

@@ -0,0 +1,525 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.28.1
+// 	protoc        v3.12.4
+// source: v1/request/sql.proto
+
+package request
+
+import (
+	_ "github.com/mwitkow/go-proto-validators"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type TransactionBeginRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Token      string `protobuf:"bytes,1,opt,name=Token,proto3" json:"Token,omitempty"`
+	Namespace  string `protobuf:"bytes,2,opt,name=Namespace,proto3" json:"Namespace,omitempty"`
+	DataSource string `protobuf:"bytes,3,opt,name=DataSource,proto3" json:"DataSource,omitempty"`
+}
+
+func (x *TransactionBeginRequest) Reset() {
+	*x = TransactionBeginRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_v1_request_sql_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *TransactionBeginRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TransactionBeginRequest) ProtoMessage() {}
+
+func (x *TransactionBeginRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_v1_request_sql_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use TransactionBeginRequest.ProtoReflect.Descriptor instead.
+func (*TransactionBeginRequest) Descriptor() ([]byte, []int) {
+	return file_v1_request_sql_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *TransactionBeginRequest) GetToken() string {
+	if x != nil {
+		return x.Token
+	}
+	return ""
+}
+
+func (x *TransactionBeginRequest) GetNamespace() string {
+	if x != nil {
+		return x.Namespace
+	}
+	return ""
+}
+
+func (x *TransactionBeginRequest) GetDataSource() string {
+	if x != nil {
+		return x.DataSource
+	}
+	return ""
+}
+
+type TransactionEndRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+}
+
+func (x *TransactionEndRequest) Reset() {
+	*x = TransactionEndRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_v1_request_sql_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *TransactionEndRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TransactionEndRequest) ProtoMessage() {}
+
+func (x *TransactionEndRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_v1_request_sql_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use TransactionEndRequest.ProtoReflect.Descriptor instead.
+func (*TransactionEndRequest) Descriptor() ([]byte, []int) {
+	return file_v1_request_sql_proto_rawDescGZIP(), []int{1}
+}
+
+type ExecuteRawSqlRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SQL           string `protobuf:"bytes,1,opt,name=SQL,proto3" json:"SQL,omitempty"`
+	ExecuteParams string `protobuf:"bytes,2,opt,name=ExecuteParams,proto3" json:"ExecuteParams,omitempty"`
+}
+
+func (x *ExecuteRawSqlRequest) Reset() {
+	*x = ExecuteRawSqlRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_v1_request_sql_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ExecuteRawSqlRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ExecuteRawSqlRequest) ProtoMessage() {}
+
+func (x *ExecuteRawSqlRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_v1_request_sql_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ExecuteRawSqlRequest.ProtoReflect.Descriptor instead.
+func (*ExecuteRawSqlRequest) Descriptor() ([]byte, []int) {
+	return file_v1_request_sql_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *ExecuteRawSqlRequest) GetSQL() string {
+	if x != nil {
+		return x.SQL
+	}
+	return ""
+}
+
+func (x *ExecuteRawSqlRequest) GetExecuteParams() string {
+	if x != nil {
+		return x.ExecuteParams
+	}
+	return ""
+}
+
+type ExecuteSqlRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Name          string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
+	ExecuteParams string `protobuf:"bytes,2,opt,name=ExecuteParams,proto3" json:"ExecuteParams,omitempty"`
+}
+
+func (x *ExecuteSqlRequest) Reset() {
+	*x = ExecuteSqlRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_v1_request_sql_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ExecuteSqlRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ExecuteSqlRequest) ProtoMessage() {}
+
+func (x *ExecuteSqlRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_v1_request_sql_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ExecuteSqlRequest.ProtoReflect.Descriptor instead.
+func (*ExecuteSqlRequest) Descriptor() ([]byte, []int) {
+	return file_v1_request_sql_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *ExecuteSqlRequest) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *ExecuteSqlRequest) GetExecuteParams() string {
+	if x != nil {
+		return x.ExecuteParams
+	}
+	return ""
+}
+
+type TransactionOperation struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Types that are assignable to Request:
+	//
+	//	*TransactionOperation_TransactionBeginRequest
+	//	*TransactionOperation_TransactionEndRequest
+	//	*TransactionOperation_ExecuteRawSqlRequest
+	//	*TransactionOperation_ExecuteSqlRequest
+	Request isTransactionOperation_Request `protobuf_oneof:"Request"`
+}
+
+func (x *TransactionOperation) Reset() {
+	*x = TransactionOperation{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_v1_request_sql_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *TransactionOperation) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TransactionOperation) ProtoMessage() {}
+
+func (x *TransactionOperation) ProtoReflect() protoreflect.Message {
+	mi := &file_v1_request_sql_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use TransactionOperation.ProtoReflect.Descriptor instead.
+func (*TransactionOperation) Descriptor() ([]byte, []int) {
+	return file_v1_request_sql_proto_rawDescGZIP(), []int{4}
+}
+
+func (m *TransactionOperation) GetRequest() isTransactionOperation_Request {
+	if m != nil {
+		return m.Request
+	}
+	return nil
+}
+
+func (x *TransactionOperation) GetTransactionBeginRequest() *TransactionBeginRequest {
+	if x, ok := x.GetRequest().(*TransactionOperation_TransactionBeginRequest); ok {
+		return x.TransactionBeginRequest
+	}
+	return nil
+}
+
+func (x *TransactionOperation) GetTransactionEndRequest() *TransactionEndRequest {
+	if x, ok := x.GetRequest().(*TransactionOperation_TransactionEndRequest); ok {
+		return x.TransactionEndRequest
+	}
+	return nil
+}
+
+func (x *TransactionOperation) GetExecuteRawSqlRequest() *ExecuteRawSqlRequest {
+	if x, ok := x.GetRequest().(*TransactionOperation_ExecuteRawSqlRequest); ok {
+		return x.ExecuteRawSqlRequest
+	}
+	return nil
+}
+
+func (x *TransactionOperation) GetExecuteSqlRequest() *ExecuteSqlRequest {
+	if x, ok := x.GetRequest().(*TransactionOperation_ExecuteSqlRequest); ok {
+		return x.ExecuteSqlRequest
+	}
+	return nil
+}
+
+type isTransactionOperation_Request interface {
+	isTransactionOperation_Request()
+}
+
+type TransactionOperation_TransactionBeginRequest struct {
+	TransactionBeginRequest *TransactionBeginRequest `protobuf:"bytes,1,opt,name=TransactionBeginRequest,proto3,oneof"`
+}
+
+type TransactionOperation_TransactionEndRequest struct {
+	TransactionEndRequest *TransactionEndRequest `protobuf:"bytes,2,opt,name=TransactionEndRequest,proto3,oneof"`
+}
+
+type TransactionOperation_ExecuteRawSqlRequest struct {
+	ExecuteRawSqlRequest *ExecuteRawSqlRequest `protobuf:"bytes,3,opt,name=ExecuteRawSqlRequest,proto3,oneof"`
+}
+
+type TransactionOperation_ExecuteSqlRequest struct {
+	ExecuteSqlRequest *ExecuteSqlRequest `protobuf:"bytes,4,opt,name=ExecuteSqlRequest,proto3,oneof"`
+}
+
+func (*TransactionOperation_TransactionBeginRequest) isTransactionOperation_Request() {}
+
+func (*TransactionOperation_TransactionEndRequest) isTransactionOperation_Request() {}
+
+func (*TransactionOperation_ExecuteRawSqlRequest) isTransactionOperation_Request() {}
+
+func (*TransactionOperation_ExecuteSqlRequest) isTransactionOperation_Request() {}
+
+var File_v1_request_sql_proto protoreflect.FileDescriptor
+
+var file_v1_request_sql_proto_rawDesc = []byte{
+	0x0a, 0x14, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2f, 0x73, 0x71, 0x6c,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x77, 0x69, 0x74,
+	0x6b, 0x6f, 0x77, 0x2f, 0x67, 0x6f, 0x2d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x76, 0x61, 0x6c,
+	0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f,
+	0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x85, 0x01, 0x0a, 0x17, 0x54, 0x72, 0x61, 0x6e,
+	0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x42, 0x06, 0xe2, 0xdf, 0x1f, 0x02, 0x58, 0x01, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65,
+	0x6e, 0x12, 0x24, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe2, 0xdf, 0x1f, 0x02, 0x58, 0x01, 0x52, 0x09, 0x4e, 0x61,
+	0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x53,
+	0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe2, 0xdf, 0x1f,
+	0x02, 0x58, 0x01, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22,
+	0x17, 0x0a, 0x15, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e,
+	0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x56, 0x0a, 0x14, 0x45, 0x78, 0x65, 0x63,
+	0x75, 0x74, 0x65, 0x52, 0x61, 0x77, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x18, 0x0a, 0x03, 0x53, 0x51, 0x4c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xe2,
+	0xdf, 0x1f, 0x02, 0x58, 0x01, 0x52, 0x03, 0x53, 0x51, 0x4c, 0x12, 0x24, 0x0a, 0x0d, 0x45, 0x78,
+	0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
+	0x22, 0x55, 0x0a, 0x11, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x42, 0x06, 0xe2, 0xdf, 0x1f, 0x02, 0x58, 0x01, 0x52, 0x04, 0x4e, 0x61, 0x6d,
+	0x65, 0x12, 0x24, 0x0a, 0x0d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61,
+	0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
+	0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0xf8, 0x02, 0x0a, 0x14, 0x54, 0x72, 0x61, 0x6e,
+	0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x12, 0x5c, 0x0a, 0x17, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42,
+	0x65, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x6e,
+	0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x17, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
+	0x6f, 0x6e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x56,
+	0x0a, 0x15, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e,
+	0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
+	0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52,
+	0x15, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x53, 0x0a, 0x14, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
+	0x65, 0x52, 0x61, 0x77, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x45,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x61, 0x77, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x61,
+	0x77, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x11, 0x45,
+	0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x48, 0x00, 0x52, 0x11, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x42, 0x1f, 0x5a, 0x1d, 0x64, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, 0x70,
+	0x63, 0x5f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_v1_request_sql_proto_rawDescOnce sync.Once
+	file_v1_request_sql_proto_rawDescData = file_v1_request_sql_proto_rawDesc
+)
+
+func file_v1_request_sql_proto_rawDescGZIP() []byte {
+	file_v1_request_sql_proto_rawDescOnce.Do(func() {
+		file_v1_request_sql_proto_rawDescData = protoimpl.X.CompressGZIP(file_v1_request_sql_proto_rawDescData)
+	})
+	return file_v1_request_sql_proto_rawDescData
+}
+
+var file_v1_request_sql_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
+var file_v1_request_sql_proto_goTypes = []interface{}{
+	(*TransactionBeginRequest)(nil), // 0: request.TransactionBeginRequest
+	(*TransactionEndRequest)(nil),   // 1: request.TransactionEndRequest
+	(*ExecuteRawSqlRequest)(nil),    // 2: request.ExecuteRawSqlRequest
+	(*ExecuteSqlRequest)(nil),       // 3: request.ExecuteSqlRequest
+	(*TransactionOperation)(nil),    // 4: request.TransactionOperation
+}
+var file_v1_request_sql_proto_depIdxs = []int32{
+	0, // 0: request.TransactionOperation.TransactionBeginRequest:type_name -> request.TransactionBeginRequest
+	1, // 1: request.TransactionOperation.TransactionEndRequest:type_name -> request.TransactionEndRequest
+	2, // 2: request.TransactionOperation.ExecuteRawSqlRequest:type_name -> request.ExecuteRawSqlRequest
+	3, // 3: request.TransactionOperation.ExecuteSqlRequest:type_name -> request.ExecuteSqlRequest
+	4, // [4:4] is the sub-list for method output_type
+	4, // [4:4] is the sub-list for method input_type
+	4, // [4:4] is the sub-list for extension type_name
+	4, // [4:4] is the sub-list for extension extendee
+	0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_v1_request_sql_proto_init() }
+func file_v1_request_sql_proto_init() {
+	if File_v1_request_sql_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_v1_request_sql_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*TransactionBeginRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_v1_request_sql_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*TransactionEndRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_v1_request_sql_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ExecuteRawSqlRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_v1_request_sql_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ExecuteSqlRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_v1_request_sql_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*TransactionOperation); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	file_v1_request_sql_proto_msgTypes[4].OneofWrappers = []interface{}{
+		(*TransactionOperation_TransactionBeginRequest)(nil),
+		(*TransactionOperation_TransactionEndRequest)(nil),
+		(*TransactionOperation_ExecuteRawSqlRequest)(nil),
+		(*TransactionOperation_ExecuteSqlRequest)(nil),
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_v1_request_sql_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   5,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_v1_request_sql_proto_goTypes,
+		DependencyIndexes: file_v1_request_sql_proto_depIdxs,
+		MessageInfos:      file_v1_request_sql_proto_msgTypes,
+	}.Build()
+	File_v1_request_sql_proto = out.File
+	file_v1_request_sql_proto_rawDesc = nil
+	file_v1_request_sql_proto_goTypes = nil
+	file_v1_request_sql_proto_depIdxs = nil
+}

+ 76 - 0
grpc_client/v1/request/sql.validator.pb.go

@@ -0,0 +1,76 @@
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
+// source: v1/request/sql.proto
+
+package request
+
+import (
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	_ "github.com/mwitkow/go-proto-validators"
+	github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+func (this *TransactionBeginRequest) Validate() error {
+	if this.Token == "" {
+		return github_com_mwitkow_go_proto_validators.FieldError("Token", fmt.Errorf(`value '%v' must not be an empty string`, this.Token))
+	}
+	if this.Namespace == "" {
+		return github_com_mwitkow_go_proto_validators.FieldError("Namespace", fmt.Errorf(`value '%v' must not be an empty string`, this.Namespace))
+	}
+	if this.DataSource == "" {
+		return github_com_mwitkow_go_proto_validators.FieldError("DataSource", fmt.Errorf(`value '%v' must not be an empty string`, this.DataSource))
+	}
+	return nil
+}
+func (this *TransactionEndRequest) Validate() error {
+	return nil
+}
+func (this *ExecuteRawSqlRequest) Validate() error {
+	if this.SQL == "" {
+		return github_com_mwitkow_go_proto_validators.FieldError("SQL", fmt.Errorf(`value '%v' must not be an empty string`, this.SQL))
+	}
+	return nil
+}
+func (this *ExecuteSqlRequest) Validate() error {
+	if this.Name == "" {
+		return github_com_mwitkow_go_proto_validators.FieldError("Name", fmt.Errorf(`value '%v' must not be an empty string`, this.Name))
+	}
+	return nil
+}
+func (this *TransactionOperation) Validate() error {
+	if oneOfNester, ok := this.GetRequest().(*TransactionOperation_TransactionBeginRequest); ok {
+		if oneOfNester.TransactionBeginRequest != nil {
+			if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(oneOfNester.TransactionBeginRequest); err != nil {
+				return github_com_mwitkow_go_proto_validators.FieldError("TransactionBeginRequest", err)
+			}
+		}
+	}
+	if oneOfNester, ok := this.GetRequest().(*TransactionOperation_TransactionEndRequest); ok {
+		if oneOfNester.TransactionEndRequest != nil {
+			if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(oneOfNester.TransactionEndRequest); err != nil {
+				return github_com_mwitkow_go_proto_validators.FieldError("TransactionEndRequest", err)
+			}
+		}
+	}
+	if oneOfNester, ok := this.GetRequest().(*TransactionOperation_ExecuteRawSqlRequest); ok {
+		if oneOfNester.ExecuteRawSqlRequest != nil {
+			if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(oneOfNester.ExecuteRawSqlRequest); err != nil {
+				return github_com_mwitkow_go_proto_validators.FieldError("ExecuteRawSqlRequest", err)
+			}
+		}
+	}
+	if oneOfNester, ok := this.GetRequest().(*TransactionOperation_ExecuteSqlRequest); ok {
+		if oneOfNester.ExecuteSqlRequest != nil {
+			if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(oneOfNester.ExecuteSqlRequest); err != nil {
+				return github_com_mwitkow_go_proto_validators.FieldError("ExecuteSqlRequest", err)
+			}
+		}
+	}
+	return nil
+}

+ 77 - 0
grpc_client/v1/sql.pb.go

@@ -0,0 +1,77 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.28.1
+// 	protoc        v3.12.4
+// source: v1/sql.proto
+
+package v1
+
+import (
+	"git.sxidc.com/service-supports/ds-sdk/grpc_client/v1/request"
+	empty "github.com/golang/protobuf/ptypes/empty"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+var File_v1_sql_proto protoreflect.FileDescriptor
+
+var file_v1_sql_proto_rawDesc = []byte{
+	0x0a, 0x0c, 0x76, 0x31, 0x2f, 0x73, 0x71, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02,
+	0x76, 0x31, 0x1a, 0x14, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2f, 0x73,
+	0x71, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x58, 0x0a, 0x0a, 0x53, 0x71, 0x6c, 0x53, 0x65, 0x72, 0x76,
+	0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
+	0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x72, 0x61,
+	0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
+	0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42,
+	0x17, 0x5a, 0x15, 0x64, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x61,
+	0x70, 0x69, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var file_v1_sql_proto_goTypes = []interface{}{
+	(*request.TransactionOperation)(nil), // 0: request.TransactionOperation
+	(*empty.Empty)(nil),                  // 1: google.protobuf.Empty
+}
+var file_v1_sql_proto_depIdxs = []int32{
+	0, // 0: v1.SqlService.Transaction:input_type -> request.TransactionOperation
+	1, // 1: v1.SqlService.Transaction:output_type -> google.protobuf.Empty
+	1, // [1:2] is the sub-list for method output_type
+	0, // [0:1] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_v1_sql_proto_init() }
+func file_v1_sql_proto_init() {
+	if File_v1_sql_proto != nil {
+		return
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_v1_sql_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   0,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_v1_sql_proto_goTypes,
+		DependencyIndexes: file_v1_sql_proto_depIdxs,
+	}.Build()
+	File_v1_sql_proto = out.File
+	file_v1_sql_proto_rawDesc = nil
+	file_v1_sql_proto_goTypes = nil
+	file_v1_sql_proto_depIdxs = nil
+}

+ 139 - 0
grpc_client/v1/sql_grpc.pb.go

@@ -0,0 +1,139 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc             v3.12.4
+// source: v1/sql.proto
+
+package v1
+
+import (
+	context "context"
+	"git.sxidc.com/service-supports/ds-sdk/grpc_client/v1/request"
+	empty "github.com/golang/protobuf/ptypes/empty"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// SqlServiceClient is the client API for SqlService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type SqlServiceClient interface {
+	Transaction(ctx context.Context, opts ...grpc.CallOption) (SqlService_TransactionClient, error)
+}
+
+type sqlServiceClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewSqlServiceClient(cc grpc.ClientConnInterface) SqlServiceClient {
+	return &sqlServiceClient{cc}
+}
+
+func (c *sqlServiceClient) Transaction(ctx context.Context, opts ...grpc.CallOption) (SqlService_TransactionClient, error) {
+	stream, err := c.cc.NewStream(ctx, &SqlService_ServiceDesc.Streams[0], "/v1.SqlService/Transaction", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &sqlServiceTransactionClient{stream}
+	return x, nil
+}
+
+type SqlService_TransactionClient interface {
+	Send(*request.TransactionOperation) error
+	Recv() (*empty.Empty, error)
+	grpc.ClientStream
+}
+
+type sqlServiceTransactionClient struct {
+	grpc.ClientStream
+}
+
+func (x *sqlServiceTransactionClient) Send(m *request.TransactionOperation) error {
+	return x.ClientStream.SendMsg(m)
+}
+
+func (x *sqlServiceTransactionClient) Recv() (*empty.Empty, error) {
+	m := new(empty.Empty)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+// SqlServiceServer is the server API for SqlService service.
+// All implementations must embed UnimplementedSqlServiceServer
+// for forward compatibility
+type SqlServiceServer interface {
+	Transaction(SqlService_TransactionServer) error
+	mustEmbedUnimplementedSqlServiceServer()
+}
+
+// UnimplementedSqlServiceServer must be embedded to have forward compatible implementations.
+type UnimplementedSqlServiceServer struct {
+}
+
+func (UnimplementedSqlServiceServer) Transaction(SqlService_TransactionServer) error {
+	return status.Errorf(codes.Unimplemented, "method Transaction not implemented")
+}
+func (UnimplementedSqlServiceServer) mustEmbedUnimplementedSqlServiceServer() {}
+
+// UnsafeSqlServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to SqlServiceServer will
+// result in compilation errors.
+type UnsafeSqlServiceServer interface {
+	mustEmbedUnimplementedSqlServiceServer()
+}
+
+func RegisterSqlServiceServer(s grpc.ServiceRegistrar, srv SqlServiceServer) {
+	s.RegisterService(&SqlService_ServiceDesc, srv)
+}
+
+func _SqlService_Transaction_Handler(srv interface{}, stream grpc.ServerStream) error {
+	return srv.(SqlServiceServer).Transaction(&sqlServiceTransactionServer{stream})
+}
+
+type SqlService_TransactionServer interface {
+	Send(*empty.Empty) error
+	Recv() (*request.TransactionOperation, error)
+	grpc.ServerStream
+}
+
+type sqlServiceTransactionServer struct {
+	grpc.ServerStream
+}
+
+func (x *sqlServiceTransactionServer) Send(m *empty.Empty) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+func (x *sqlServiceTransactionServer) Recv() (*request.TransactionOperation, error) {
+	m := new(request.TransactionOperation)
+	if err := x.ServerStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+// SqlService_ServiceDesc is the grpc.ServiceDesc for SqlService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var SqlService_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "v1.SqlService",
+	HandlerType: (*SqlServiceServer)(nil),
+	Methods:     []grpc.MethodDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "Transaction",
+			Handler:       _SqlService_Transaction_Handler,
+			ServerStreams: true,
+			ClientStreams: true,
+		},
+	},
+	Metadata: "v1/sql.proto",
+}

+ 20 - 7
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/grpc_client"
 )
 
 var sdkInstance *SDK
@@ -10,16 +11,17 @@ func GetInstance() *SDK {
 	return sdkInstance
 }
 
-func InitInstance(token string, baseUrl string, namespace string, dataSource string, opts ...Option) error {
+func InitInstance(token string, address string, httpPort string, grpcPort string, namespace string, dataSource string, opts ...Option) error {
 	if sdkInstance != nil {
 		return nil
 	}
 
 	options := &Options{
-		token:      token,
-		baseUrl:    baseUrl,
-		namespace:  namespace,
-		dataSource: dataSource,
+		token:       token,
+		baseUrl:     "http://" + address + ":" + httpPort,
+		grpcAddress: address + ":" + grpcPort,
+		namespace:   namespace,
+		dataSource:  dataSource,
 	}
 
 	for _, opt := range opts {
@@ -28,9 +30,15 @@ func InitInstance(token string, baseUrl string, namespace string, dataSource str
 
 	c := client.New(options.timeout)
 
+	grpcClient, err := grpc_client.NewClient(options.grpcAddress, options.timeout)
+	if err != nil {
+		return err
+	}
+
 	sdkInstance = &SDK{
-		options: options,
-		client:  c,
+		options:    options,
+		client:     c,
+		grpcClient: grpcClient,
 	}
 
 	return nil
@@ -41,6 +49,11 @@ func DestroyInstance() error {
 		return nil
 	}
 
+	err := grpc_client.Destroy(sdkInstance.grpcClient)
+	if err != nil {
+		return err
+	}
+
 	sdkInstance = nil
 
 	return nil

+ 5 - 4
sdk/options.go

@@ -14,10 +14,11 @@ func WithTimeout(timeout time.Duration) Option {
 
 type Options struct {
 	// 必传
-	token      string
-	baseUrl    string
-	namespace  string
-	dataSource string
+	token       string
+	baseUrl     string
+	grpcAddress string
+	namespace   string
+	dataSource  string
 
 	// 选传
 	timeout time.Duration

+ 144 - 4
sdk/sdk.go

@@ -1,14 +1,20 @@
 package sdk
 
 import (
+	"encoding/json"
 	"errors"
 	"git.sxidc.com/go-tools/utils/strutils"
 	"git.sxidc.com/service-supports/ds-sdk/client"
+	"git.sxidc.com/service-supports/ds-sdk/grpc_client"
+	v1 "git.sxidc.com/service-supports/ds-sdk/grpc_client/v1"
+	"git.sxidc.com/service-supports/ds-sdk/grpc_client/v1/request"
+	"io"
 )
 
 type SDK struct {
-	options *Options
-	client  *client.Client
+	options    *Options
+	client     *client.Client
+	grpcClient *grpc_client.Client
 }
 
 func (s *SDK) CreateDataContainer(name string, spec map[string]any) error {
@@ -52,7 +58,7 @@ func (s *SDK) GetDataContainers(name string, pageNo int, pageSize int) ([]client
 
 // TODO 增加Event版本的Container创建
 
-func (s *SDK) ExecuteRawSql(sql string) ([]map[string]any, error) {
+func (s *SDK) ExecuteRawSql(sql string, executeParams map[string]any) ([]map[string]any, error) {
 	if strutils.IsStringEmpty(sql) {
 		return make([]map[string]any, 0), nil
 	}
@@ -60,7 +66,7 @@ func (s *SDK) ExecuteRawSql(sql string) ([]map[string]any, error) {
 	options := s.options
 
 	results, err := s.client.ExecuteRawSql(options.token, options.baseUrl,
-		options.namespace, options.dataSource, sql)
+		options.namespace, options.dataSource, sql, executeParams)
 	if err != nil {
 		return nil, err
 	}
@@ -115,3 +121,137 @@ func (s *SDK) ExecuteSql(name string, executeParams map[string]any) ([]map[strin
 
 	return results, nil
 }
+
+type TxFunc func(tx *Transaction) error
+
+type Transaction struct {
+	stream v1.SqlService_TransactionClient
+}
+
+func (tx *Transaction) ExecuteRawSql(sql string, executeParams map[string]any) error {
+	var retErr error
+
+	defer func() {
+		if retErr != nil {
+			innerErr := tx.stream.CloseSend()
+			if innerErr != nil {
+				panic(innerErr)
+			}
+		}
+	}()
+
+	executeParamsJsonBytes, err := json.Marshal(executeParams)
+	if err != nil {
+		retErr = err
+		return retErr
+	}
+
+	err = tx.stream.SendMsg(&request.TransactionOperation{
+		Request: &request.TransactionOperation_ExecuteRawSqlRequest{
+			ExecuteRawSqlRequest: &request.ExecuteRawSqlRequest{
+				SQL:           sql,
+				ExecuteParams: string(executeParamsJsonBytes),
+			},
+		},
+	})
+	if err != nil {
+		retErr = err
+		return retErr
+	}
+
+	_, err = tx.stream.Recv()
+	if err != nil {
+		retErr = err
+		return retErr
+	}
+
+	return nil
+}
+
+func (tx *Transaction) ExecuteSql(name string, executeParams map[string]any) error {
+	var retErr error
+
+	defer func() {
+		if retErr != nil {
+			innerErr := tx.stream.CloseSend()
+			if innerErr != nil {
+				panic(innerErr)
+			}
+		}
+	}()
+
+	executeParamsJsonBytes, err := json.Marshal(executeParams)
+	if err != nil {
+		retErr = err
+		return retErr
+	}
+
+	err = tx.stream.Send(&request.TransactionOperation{
+		Request: &request.TransactionOperation_ExecuteSqlRequest{
+			ExecuteSqlRequest: &request.ExecuteSqlRequest{
+				Name:          name,
+				ExecuteParams: string(executeParamsJsonBytes),
+			},
+		},
+	})
+	if err != nil {
+		retErr = err
+		return retErr
+	}
+
+	_, err = tx.stream.Recv()
+	if err != nil {
+		retErr = err
+		return retErr
+	}
+
+	return nil
+}
+
+func (s *SDK) Transaction(txFunc TxFunc) error {
+	stream, err := s.grpcClient.Transaction()
+	if err != nil {
+		return err
+	}
+
+	defer func() {
+		innerErr := stream.CloseSend()
+		if innerErr != nil {
+			panic(innerErr)
+		}
+	}()
+
+	err = stream.Send(&request.TransactionOperation{
+		Request: &request.TransactionOperation_TransactionBeginRequest{
+			TransactionBeginRequest: &request.TransactionBeginRequest{
+				Token:      s.options.token,
+				Namespace:  s.options.namespace,
+				DataSource: s.options.dataSource,
+			},
+		}})
+	if err != nil {
+		return err
+	}
+
+	err = txFunc(&Transaction{
+		stream: stream,
+	})
+	if err != nil {
+		return err
+	}
+
+	err = stream.Send(&request.TransactionOperation{
+		Request: &request.TransactionOperation_TransactionEndRequest{
+			TransactionEndRequest: &request.TransactionEndRequest{},
+		}})
+	if err != nil {
+		return err
+	}
+
+	_, err = stream.Recv()
+	if err != nil && err != io.EOF {
+		return err
+	}
+
+	return nil
+}