Browse Source

完成数据库基础设施测试

yjp 9 months ago
parent
commit
cab4f26c9f

+ 25 - 19
framework/core/infrastructure/database/sql/result.go

@@ -1,7 +1,7 @@
 package sql
 
 import (
-	"fmt"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger"
 	"git.sxidc.com/go-framework/baize/framework/core/tag/sql/sql_result"
 	"git.sxidc.com/go-tools/utils/reflectutils"
 	"git.sxidc.com/go-tools/utils/strutils"
@@ -20,15 +20,21 @@ const (
 // Result 查询结果
 type Result map[string]any
 
-// ColumnValueStringAsTime 将string类型的列值转化为time.Time
+// ColumnValueTime 以time.Time类型获取列值
 // 参数:
 // - columnName: 列名
 // 返回值:
-// - 转换为time.Time的列值
-func (result Result) ColumnValueStringAsTime(columnName string) time.Time {
+// - time.Time类型的列值
+func (result Result) ColumnValueTime(columnName string) time.Time {
 	value, ok := result[columnName].(string)
 	if !ok {
-		return time.Time{}
+		value, ok := result[columnName].(time.Time)
+		if !ok {
+			logger.GetInstance().Error(errors.New("无法转换为时间类型"))
+			return time.Time{}
+		}
+
+		return value
 	}
 
 	layout := resultTimeSecFormat
@@ -64,7 +70,7 @@ func (result Result) ColumnValueStringAsTime(columnName string) time.Time {
 func (result Result) ColumnValueBool(columnName string) bool {
 	value, err := reflectutils.ToBool(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return false
 	}
 
@@ -79,7 +85,7 @@ func (result Result) ColumnValueBool(columnName string) bool {
 func (result Result) ColumnValueString(columnName string) string {
 	value, err := reflectutils.ToString(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return ""
 	}
 
@@ -94,7 +100,7 @@ func (result Result) ColumnValueString(columnName string) string {
 func (result Result) ColumnValueInt(columnName string) int {
 	value, err := reflectutils.ToInt64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -109,7 +115,7 @@ func (result Result) ColumnValueInt(columnName string) int {
 func (result Result) ColumnValueInt8(columnName string) int8 {
 	value, err := reflectutils.ToInt64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -124,7 +130,7 @@ func (result Result) ColumnValueInt8(columnName string) int8 {
 func (result Result) ColumnValueInt16(columnName string) int16 {
 	value, err := reflectutils.ToInt64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -139,7 +145,7 @@ func (result Result) ColumnValueInt16(columnName string) int16 {
 func (result Result) ColumnValueInt32(columnName string) int32 {
 	value, err := reflectutils.ToInt64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -154,7 +160,7 @@ func (result Result) ColumnValueInt32(columnName string) int32 {
 func (result Result) ColumnValueInt64(columnName string) int64 {
 	value, err := reflectutils.ToInt64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -169,7 +175,7 @@ func (result Result) ColumnValueInt64(columnName string) int64 {
 func (result Result) ColumnValueUint(columnName string) uint {
 	value, err := reflectutils.ToUint64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -184,7 +190,7 @@ func (result Result) ColumnValueUint(columnName string) uint {
 func (result Result) ColumnValueUint8(columnName string) uint8 {
 	value, err := reflectutils.ToUint64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -199,7 +205,7 @@ func (result Result) ColumnValueUint8(columnName string) uint8 {
 func (result Result) ColumnValueUint16(columnName string) uint16 {
 	value, err := reflectutils.ToUint64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -214,7 +220,7 @@ func (result Result) ColumnValueUint16(columnName string) uint16 {
 func (result Result) ColumnValueUint32(columnName string) uint32 {
 	value, err := reflectutils.ToUint64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -229,7 +235,7 @@ func (result Result) ColumnValueUint32(columnName string) uint32 {
 func (result Result) ColumnValueUint64(columnName string) uint64 {
 	value, err := reflectutils.ToUint64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -244,7 +250,7 @@ func (result Result) ColumnValueUint64(columnName string) uint64 {
 func (result Result) ColumnValueFloat32(columnName string) float32 {
 	value, err := reflectutils.ToFloat64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 
@@ -259,7 +265,7 @@ func (result Result) ColumnValueFloat32(columnName string) float32 {
 func (result Result) ColumnValueFloat64(columnName string) float64 {
 	value, err := reflectutils.ToFloat64(result[columnName])
 	if err != nil {
-		fmt.Println(err)
+		logger.GetInstance().Error(err)
 		return 0
 	}
 

+ 1 - 1
go.mod

@@ -4,7 +4,7 @@ go 1.22.3
 
 require (
 	git.sxidc.com/go-tools/utils v1.5.23
-	git.sxidc.com/service-supports/ds-sdk v0.10.7
+	git.sxidc.com/service-supports/ds-sdk v0.10.8
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/gin-gonic/gin v1.10.0
 	github.com/go-playground/locales v0.14.1

+ 2 - 2
go.sum

@@ -2,8 +2,8 @@ git.sxidc.com/go-tools/api_binding v1.3.23 h1:vgCdYq09aiw7Vs9JeOR0OZLOjezbHugQ/3
 git.sxidc.com/go-tools/api_binding v1.3.23/go.mod h1:SmUnRrMtODonLzWmWCGQN9uAB2TjH8g5yEKFnp4rEgU=
 git.sxidc.com/go-tools/utils v1.5.23 h1:Kbcj+EafFVssRa6i1jnILi+LddLWMDtyvRzuV26C6fU=
 git.sxidc.com/go-tools/utils v1.5.23/go.mod h1:uTDb6QK5JZzK5+Fzsfeng7TwmnRDZiTY6JLYxIX94Qw=
-git.sxidc.com/service-supports/ds-sdk v0.10.7 h1:Ok552Pom8g50Fsrb/OWyIhB6axuPp5hS1wcJtTZu1JU=
-git.sxidc.com/service-supports/ds-sdk v0.10.7/go.mod h1:NtuKH9TDWGlgvhXKN2eGP69X0HrG3nK8VB0Tu3Ko7Hg=
+git.sxidc.com/service-supports/ds-sdk v0.10.8 h1:W/zMrF5Kx3CnGAQ03kOugVVZUA1dfxMPkURloOWKjRo=
+git.sxidc.com/service-supports/ds-sdk v0.10.8/go.mod h1:NtuKH9TDWGlgvhXKN2eGP69X0HrG3nK8VB0Tu3Ko7Hg=
 git.sxidc.com/service-supports/fserr v0.3.2 h1:5/FCr8o2jd1kNsp5tH/ADjB9fr091JZXMMZ15ZvNZzs=
 git.sxidc.com/service-supports/fserr v0.3.2/go.mod h1:W54RoA71mfex+zARuH/iMnQPMnBXQ23qXXOkwUh2sVQ=
 git.sxidc.com/service-supports/fslog v0.5.9 h1:q2XIK2o/fk/qmByy4x5kKLC+k7kolT5LrXHcWRSffXQ=

+ 129 - 32
test/cache_test.go

@@ -2,6 +2,7 @@ package test
 
 import (
 	"git.sxidc.com/go-framework/baize/framework/core/infrastructure"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/cache"
 	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/cache/local"
 	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/cache/redis"
 	"git.sxidc.com/go-tools/utils/strutils"
@@ -10,17 +11,17 @@ import (
 )
 
 func TestLocalCache(t *testing.T) {
-	cache := local.New("test")
-	testLocalCache(t, cache)
+	localhostCache := local.New("test")
+	testLocalCache(t, localhostCache)
 }
 
 func TestRedisCache(t *testing.T) {
-	cache, err := redis.New("localhost:30379", "", "mtyzxhc", 1, "test")
+	redisCache, err := redis.New("localhost:30379", "", "mtyzxhc", 1, "test")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	testRedisCache(t, cache)
+	testRedisCache(t, redisCache)
 }
 
 func TestCacheInfrastructure(t *testing.T) {
@@ -36,17 +37,17 @@ func TestCacheInfrastructure(t *testing.T) {
 		},
 	})
 
-	testLocalCache(t, i.LocalCache().(*local.Cache))
-	testRedisCache(t, i.RedisCache().(*redis.Cache))
+	testCache(t, i.LocalCache())
+	testCache(t, i.RedisCache())
 }
 
-func testLocalCache(t *testing.T, cache *local.Cache) {
-	err := cache.Set("test1", "test1-value", 0)
+func testLocalCache(t *testing.T, localCache *local.Cache) {
+	err := localCache.Set("test1", "test1-value", 0)
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	test1Value, err := cache.Get("test1")
+	test1Value, err := localCache.Get("test1")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -55,12 +56,12 @@ func testLocalCache(t *testing.T, cache *local.Cache) {
 		t.Fatalf("Value Error: cache %v\n", test1Value)
 	}
 
-	err = cache.Set("test2", "test2-value", 0)
+	err = localCache.Set("test2", "test2-value", 0)
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	multiValues, err := cache.GetMulti([]string{"test1", "test2"})
+	multiValues, err := localCache.GetMulti([]string{"test1", "test2"})
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -73,7 +74,7 @@ func testLocalCache(t *testing.T, cache *local.Cache) {
 		t.Fatalf("Value Error: cache %v\n", multiValues)
 	}
 
-	allValues, err := cache.GetAll()
+	allValues, err := localCache.GetAll()
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -86,12 +87,12 @@ func testLocalCache(t *testing.T, cache *local.Cache) {
 		t.Fatalf("Value Error: cache %v\n", allValues)
 	}
 
-	err = cache.Delete("test2")
+	err = localCache.Delete("test2")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	test2Value, err := cache.Get("test2")
+	test2Value, err := localCache.Get("test2")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -100,12 +101,12 @@ func testLocalCache(t *testing.T, cache *local.Cache) {
 		t.Fatalf("Delete Value Error: cache %v\n", test2Value)
 	}
 
-	err = cache.Clear()
+	err = localCache.Clear()
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	allValues, err = cache.GetAll()
+	allValues, err = localCache.GetAll()
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -114,14 +115,14 @@ func testLocalCache(t *testing.T, cache *local.Cache) {
 		t.Fatalf("Clear Value Error: cache %v\n", allValues)
 	}
 
-	err = cache.Set("test", "test-value", 1)
+	err = localCache.Set("test", "test-value", 1)
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
 	time.Sleep(1500 * time.Millisecond)
 
-	testValue, err := cache.Get("test")
+	testValue, err := localCache.Get("test")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -130,19 +131,19 @@ func testLocalCache(t *testing.T, cache *local.Cache) {
 		t.Fatalf("Value Expire Error: cache %v\n", testValue)
 	}
 
-	err = cache.Clear()
+	err = localCache.Clear()
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 }
 
-func testRedisCache(t *testing.T, cache *redis.Cache) {
-	err := cache.Set("test1", "test1-value", 0)
+func testRedisCache(t *testing.T, redisCache *redis.Cache) {
+	err := redisCache.Set("test1", "test1-value", 0)
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	test1Value, err := cache.Get("test1")
+	test1Value, err := redisCache.Get("test1")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -151,12 +152,12 @@ func testRedisCache(t *testing.T, cache *redis.Cache) {
 		t.Fatalf("Value Error: cache %v\n", test1Value)
 	}
 
-	err = cache.Set("test2", "test2-value", 0)
+	err = redisCache.Set("test2", "test2-value", 0)
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	multiValues, err := cache.GetMulti([]string{"test1", "test2"})
+	multiValues, err := redisCache.GetMulti([]string{"test1", "test2"})
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -169,7 +170,7 @@ func testRedisCache(t *testing.T, cache *redis.Cache) {
 		t.Fatalf("Value Error: cache %v\n", multiValues)
 	}
 
-	allValues, err := cache.GetAll()
+	allValues, err := redisCache.GetAll()
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -182,12 +183,12 @@ func testRedisCache(t *testing.T, cache *redis.Cache) {
 		t.Fatalf("Value Error: cache %v\n", allValues)
 	}
 
-	err = cache.Delete("test2")
+	err = redisCache.Delete("test2")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	test2Value, err := cache.Get("test2")
+	test2Value, err := redisCache.Get("test2")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -196,12 +197,12 @@ func testRedisCache(t *testing.T, cache *redis.Cache) {
 		t.Fatalf("Delete Value Error: cache %v\n", test2Value)
 	}
 
-	err = cache.Clear()
+	err = redisCache.Clear()
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
-	allValues, err = cache.GetAll()
+	allValues, err = redisCache.GetAll()
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -210,14 +211,14 @@ func testRedisCache(t *testing.T, cache *redis.Cache) {
 		t.Fatalf("Clear Value Error: cache %v\n", allValues)
 	}
 
-	err = cache.Set("test", "test-value", 1)
+	err = redisCache.Set("test", "test-value", 1)
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
 
 	time.Sleep(1500 * time.Millisecond)
 
-	testValue, err := cache.Get("test")
+	testValue, err := redisCache.Get("test")
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}
@@ -226,7 +227,103 @@ func testRedisCache(t *testing.T, cache *redis.Cache) {
 		t.Fatalf("Value Expire Error: cache %v\n", testValue)
 	}
 
-	err = cache.Clear()
+	err = redisCache.Clear()
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+}
+
+func testCache(t *testing.T, cacheInterface cache.Cache) {
+	err := cache.Set(cacheInterface, "test1", "test1-value", 0)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	test1Value, err := cache.Get[string](cacheInterface, "test1")
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if test1Value != "test1-value" {
+		t.Fatalf("Value Error: cache %v\n", test1Value)
+	}
+
+	err = cache.Set(cacheInterface, "test2", "test2-value", 0)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	multiValues, err := cache.GetMulti(cacheInterface, []string{"test1", "test2"})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(multiValues) != 2 {
+		t.Fatalf("Value Error: cache %v\n", multiValues)
+	}
+
+	if multiValues["test1"] != "test1-value" || multiValues["test2"] != "test2-value" {
+		t.Fatalf("Value Error: cache %v\n", multiValues)
+	}
+
+	allValues, err := cache.GetAll(cacheInterface)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(allValues) != 2 {
+		t.Fatalf("Value Error: cache %v\n", allValues)
+	}
+
+	if allValues["test1"] != "test1-value" || allValues["test2"] != "test2-value" {
+		t.Fatalf("Value Error: cache %v\n", allValues)
+	}
+
+	err = cache.Delete(cacheInterface, "test2")
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	test2Value, err := cache.Get[string](cacheInterface, "test2")
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if strutils.IsStringNotEmpty(test2Value) {
+		t.Fatalf("Delete Value Error: cache %v\n", test2Value)
+	}
+
+	err = cache.Clear(cacheInterface)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	allValues, err = cache.GetAll(cacheInterface)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(allValues) != 0 {
+		t.Fatalf("Clear Value Error: cache %v\n", allValues)
+	}
+
+	err = cache.Set(cacheInterface, "test", "test-value", 1)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	time.Sleep(1500 * time.Millisecond)
+
+	testValue, err := cache.Get[string](cacheInterface, "test")
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if strutils.IsStringNotEmpty(testValue) {
+		t.Fatalf("Value Expire Error: cache %v\n", testValue)
+	}
+
+	err = cache.Clear(cacheInterface)
 	if err != nil {
 		t.Fatalf("%+v\n", err)
 	}

+ 20 - 0
test/data_service/base.yaml

@@ -0,0 +1,20 @@
+kind: Namespace
+spec:
+  name: baize
+
+---
+
+kind: DataSource
+spec:
+  type: database
+  namespace: baize
+  name: baize
+  spec:
+    type: postgres
+    user_name: test
+    password: "123456"
+    address: "10.0.0.84"
+    port: "30432"
+    database: test
+    max_connections: 20
+    max_idle_connections: 5

+ 26 - 0
test/data_service/data_containers/student.yaml

@@ -0,0 +1,26 @@
+kind: DataContainer
+spec:
+  namespace: baize
+  data_source: baize
+  name: test.students
+  spec:
+    table_name: test.students
+    columns:
+      - name: id
+        type: varchar(32)
+        comment: id
+        primary_key: true
+      - name: name
+        type: varchar(128)
+        comment: 姓名
+        not_null: true
+        index: true
+      - name: age
+        type: integer
+        comment: 年龄
+        not_null: true
+        index: true
+      - name: enter_time
+        type: "timestamp with time zone"
+        comment: 入学时间
+        not_null: true

+ 126 - 3
test/database_sql_test.go

@@ -119,7 +119,8 @@ func TestDatabaseSqlTableRow(t *testing.T) {
 }
 
 func TestDatabaseSqlResult(t *testing.T) {
-	timeResult := time.Now().Local().Format("2006-01-02T15:04:05") + "+08:00"
+	timeResult := time.Now().Local()
+	timeStringResult := time.Now().Local().Format("2006-01-02T15:04:05") + "+08:00"
 	stringResult := strutils.SimpleUUID()
 	boolResult := rand.Intn(2) == 0
 	intResult := rand.Int()
@@ -136,6 +137,7 @@ func TestDatabaseSqlResult(t *testing.T) {
 	float64Result := rand.Float64()
 
 	result := sql.Result{
+		"timeStr": timeStringResult,
 		"time":    timeResult,
 		"string":  stringResult,
 		"bool":    boolResult,
@@ -153,9 +155,14 @@ func TestDatabaseSqlResult(t *testing.T) {
 		"float64": float64Result,
 	}
 
-	if result.ColumnValueStringAsTime("time").Format("2006-01-02T15:04:05")+"+08:00" != timeResult {
+	if result.ColumnValueTime("timeStr").Format("2006-01-02T15:04:05")+"+08:00" != timeStringResult {
 		t.Fatalf("%+v\n", errors.Errorf("Result Error: except %v, actural %v",
-			timeResult, result.ColumnValueStringAsTime("time")))
+			timeStringResult, result.ColumnValueTime("timeStr")))
+	}
+
+	if !result.ColumnValueTime("time").Equal(timeResult) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except %v, actural %v",
+			timeResult, result.ColumnValueTime("time")))
 	}
 
 	if result.ColumnValueString("string") != stringResult {
@@ -229,6 +236,122 @@ func TestDatabaseSqlResult(t *testing.T) {
 	}
 }
 
+type Info struct {
+	ID           string    `sqlresult:"column:id"`
+	Name         string    `sqlresult:"column:name"`
+	Age          int32     `sqlresult:"column:age"`
+	EnterTime    time.Time `sqlresult:"column:enter_time"`
+	EnterTimeStr string    `sqlresult:"column:enter_time"`
+}
+
+func TestDatabaseParseSqlResult(t *testing.T) {
+	id1 := strutils.SimpleUUID()
+	name1 := strutils.SimpleUUID()
+	age1 := rand.Int31()
+	enterTime1 := time.Now().Local()
+
+	id2 := strutils.SimpleUUID()
+	name2 := strutils.SimpleUUID()
+	age2 := rand.Int31()
+	enterTime2 := time.Now().Local()
+
+	result1 := sql.Result{
+		"id":         id1,
+		"name":       name1,
+		"age":        age1,
+		"enter_time": enterTime1,
+	}
+
+	result2 := sql.Result{
+		"id":         id2,
+		"name":       name2,
+		"age":        age2,
+		"enter_time": enterTime2,
+	}
+
+	results := []sql.Result{result1, result2}
+
+	var nameResult string
+	nameResults := make([]string, 0)
+
+	err := sql.ParseSqlResultWithColumn(result1, &nameResult, "name")
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if nameResult != name1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except %v, actural %v",
+			name1, nameResult))
+	}
+
+	err = sql.ParseSqlResultWithColumn(results, &nameResults, "name")
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(nameResults) != 2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: %v", nameResults))
+	}
+
+	for _, r := range nameResults {
+		if r != name1 && r != name2 {
+			t.Fatalf("%+v\n", errors.Errorf("Result Error: %v", r))
+		}
+	}
+
+	info := new(Info)
+	infos := make([]Info, 0)
+
+	err = sql.ParseSqlResult(result2, info)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if info.ID != id2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except %v, actural %v",
+			id2, info.ID))
+	}
+
+	if info.Name != name2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except %v, actural %v",
+			name2, info.Name))
+	}
+
+	if info.Age != age2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except %v, actural %v",
+			age2, info.Age))
+	}
+
+	if info.EnterTime.Format(time.DateTime) != enterTime2.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except %v, actural %v",
+			enterTime2, info.EnterTime))
+	}
+
+	err = sql.ParseSqlResult(results, &infos)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	for _, i := range infos {
+		if i.ID != id1 && i.ID != id2 {
+			t.Fatalf("%+v\n", errors.Errorf("Result Error: %v", i.ID))
+		}
+
+		if i.Name != name1 && i.Name != name2 {
+			t.Fatalf("%+v\n", errors.Errorf("Result Error: %v", i.Name))
+		}
+
+		if i.Age != age1 && i.Age != age2 {
+			t.Fatalf("%+v\n", errors.Errorf("Result Error: %v", i.Age))
+		}
+
+		if i.EnterTime.Format(time.DateTime) != enterTime1.Format(time.DateTime) &&
+			i.EnterTime.Format(time.DateTime) != enterTime2.Format(time.DateTime) {
+			t.Fatalf("%+v\n", errors.Errorf("Result Error: %v", i.EnterTime))
+		}
+	}
+}
+
 func TestDatabaseSqlTemplate(t *testing.T) {
 	tableName := "test.students"
 

+ 669 - 0
test/database_test.go

@@ -0,0 +1,669 @@
+package test
+
+import (
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/database"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/data_service"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/operations"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/sql"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"github.com/pkg/errors"
+	"math/rand"
+	"testing"
+	"time"
+)
+
+func TestOperations(t *testing.T) {
+	dbOperations, err := operations.NewOperations(&operations.Config{
+		UserName:           "test",
+		Password:           "123456",
+		Address:            "localhost",
+		Port:               "30432",
+		Database:           "test",
+		MaxConnections:     40,
+		MaxIdleConnections: 10,
+		LogLevel:           "error",
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	testDBExecutor(t, dbOperations)
+}
+
+func TestDataService(t *testing.T) {
+	dataService, err := data_service.NewExecutor(&data_service.Config{
+		Token:          "8qe+uPgpQ2JWxu3lSyOx5EWC24/c+zJOxvFhvRLRTzU=",
+		Address:        "localhost",
+		HttpPort:       "10000",
+		GrpcPort:       "10001",
+		Namespace:      "baize",
+		DataSource:     "baize",
+		HttpTimeoutSec: 10,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	testDBExecutor(t, dataService)
+}
+
+func TestDatabase(t *testing.T) {
+	dbOperations, err := operations.NewOperations(&operations.Config{
+		UserName:           "test",
+		Password:           "123456",
+		Address:            "localhost",
+		Port:               "30432",
+		Database:           "test",
+		MaxConnections:     40,
+		MaxIdleConnections: 10,
+		LogLevel:           "error",
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	dataService, err := data_service.NewExecutor(&data_service.Config{
+		Token:          "8qe+uPgpQ2JWxu3lSyOx5EWC24/c+zJOxvFhvRLRTzU=",
+		Address:        "localhost",
+		HttpPort:       "10000",
+		GrpcPort:       "10001",
+		Namespace:      "baize",
+		DataSource:     "baize",
+		HttpTimeoutSec: 10,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	testDatabaseEntity(t, dbOperations, dbOperations)
+	testDatabase(t, dbOperations, dbOperations)
+	testDatabaseEntity(t, dataService, dataService)
+	testDatabase(t, dataService, dataService)
+
+	err = database.Transaction(dbOperations, func(tx database.Executor) error {
+		testDatabaseEntity(t, dbOperations, tx)
+		testDatabase(t, dbOperations, tx)
+		return nil
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	err = database.Transaction(dbOperations, func(tx database.Executor) error {
+		testDatabaseEntity(t, dataService, tx)
+		testDatabase(t, dataService, tx)
+		return nil
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+}
+
+func testDBExecutor(t *testing.T, dbExecutor database.Executor) {
+	id := strutils.SimpleUUID()
+	name := strutils.SimpleUUID()
+	age := rand.Int31()
+	enterTime := time.Now().Local()
+
+	_, err := dbExecutor.ExecuteRawSql(`
+INSERT INTO
+	test.students (id, name, age, enter_time)
+VALUES 
+    (?, ?, ?, ?)
+`, id, name, age, enterTime)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	results, err := dbExecutor.ExecuteRawSql(`
+SELECT 
+    *
+FROM
+	test.students
+WHERE 
+    id = ?
+`, id)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if results[0].ColumnValueString("id") != id {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id, results[0].ColumnValueString("id")))
+	}
+
+	if results[0].ColumnValueString("name") != name {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name, results[0].ColumnValueString("name")))
+	}
+
+	if results[0].ColumnValueInt32("age") != age {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age, results[0].ColumnValueInt32("age")))
+	}
+
+	if results[0].ColumnValueTime("enter_time").Format(time.DateTime) != enterTime.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime, results[0].ColumnValueTime("enter_time")))
+	}
+
+	_, err = dbExecutor.ExecuteRawSql(`
+DELETE FROM
+	test.students
+WHERE 
+    id = ?
+`, id)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	results, err = dbExecutor.ExecuteRawSql(`
+SELECT 
+    *
+FROM
+	test.students
+WHERE 
+    id = ?
+`, id)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(results) != 0 {
+		t.Fatalf("Delete Error: %+v\n", results)
+	}
+
+	_, err = dbExecutor.ExecuteRawSqlTemplate(`
+INSERT INTO
+	{{ .table_name }} (id, name, age, enter_time)
+VALUES 
+    (?, ?, ?, ?)
+`, map[string]any{"table_name": "test.students"}, id, name, age, enterTime)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	results, err = dbExecutor.ExecuteRawSqlTemplate(`
+SELECT 
+    *
+FROM
+	{{ .table_name }}
+WHERE 
+    id = ?
+`, map[string]any{"table_name": "test.students"}, id)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if results[0].ColumnValueString("id") != id {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id, results[0].ColumnValueString("id")))
+	}
+
+	if results[0].ColumnValueString("name") != name {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name, results[0].ColumnValueString("name")))
+	}
+
+	if results[0].ColumnValueInt32("age") != age {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age, results[0].ColumnValueInt32("age")))
+	}
+
+	if results[0].ColumnValueTime("enter_time").Format(time.DateTime) != enterTime.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime, results[0].ColumnValueTime("enter_time")))
+	}
+
+	_, err = dbExecutor.ExecuteRawSqlTemplate(`
+DELETE FROM
+	{{ .table_name }}
+WHERE 
+    id = ?
+`, map[string]any{"table_name": "test.students"}, id)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	results, err = dbExecutor.ExecuteRawSqlTemplate(`
+SELECT 
+    *
+FROM
+	{{ .table_name }}
+WHERE 
+    id = ?
+`, map[string]any{"table_name": "test.students"}, id)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(results) != 0 {
+		t.Fatalf("Delete Error: %+v\n", results)
+	}
+}
+
+type Student struct {
+	ID        string    `sqlmapping:"column:id" sqlresult:"column:id"`
+	Name      string    `sqlmapping:"column:name" sqlresult:"column:name"`
+	Age       int32     `sqlmapping:"column:age" sqlresult:"column:age"`
+	EnterTime time.Time `sqlmapping:"column:enter_time" sqlresult:"column:enter_time"`
+}
+
+func testDatabaseEntity(t *testing.T, writeDBExecutor database.Executor, readDBExecutor database.Executor) {
+	tableName := "test.students"
+
+	id1 := strutils.SimpleUUID()
+	name1 := "1" + strutils.SimpleUUID()
+	age1 := rand.Int31()
+	enterTime1 := time.Now().Local()
+
+	id2 := strutils.SimpleUUID()
+	name2 := "2" + strutils.SimpleUUID()
+	age2 := rand.Int31()
+	enterTime2 := time.Now().Local()
+
+	student1 := &Student{
+		ID:        id1,
+		Name:      name1,
+		Age:       age1,
+		EnterTime: enterTime1,
+	}
+
+	newStudent1 := &Student{
+		ID:        id1,
+		Name:      name2,
+		Age:       age2,
+		EnterTime: enterTime2,
+	}
+
+	student2 := &Student{
+		ID:        id2,
+		Name:      name2,
+		Age:       age2,
+		EnterTime: enterTime2,
+	}
+
+	err := database.InsertEntity(writeDBExecutor, tableName, student1)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	result, err := database.QueryOne(readDBExecutor, &sql.QueryOneExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if result.ColumnValueString("id") != id1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id1, result.ColumnValueString("id")))
+	}
+
+	if result.ColumnValueString("name") != name1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name1, result.ColumnValueString("name")))
+	}
+
+	if result.ColumnValueInt32("age") != age1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age1, result.ColumnValueInt32("age")))
+	}
+
+	if result.ColumnValueTime("enter_time").Format(time.DateTime) != enterTime1.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime1, result.ColumnValueTime("enter_time")))
+	}
+
+	err = database.UpdateEntity(writeDBExecutor, tableName, newStudent1)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	result, err = database.QueryOne(readDBExecutor, &sql.QueryOneExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if result.ColumnValueString("id") != id1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id1, result.ColumnValueString("id")))
+	}
+
+	if result.ColumnValueString("name") != name2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name2, result.ColumnValueString("name")))
+	}
+
+	if result.ColumnValueInt32("age") != age2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age2, result.ColumnValueInt32("age")))
+	}
+
+	if result.ColumnValueTime("enter_time").Format(time.DateTime) != enterTime2.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime2, result.ColumnValueTime("enter_time")))
+	}
+
+	err = database.DeleteEntity(writeDBExecutor, tableName, newStudent1)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	exist, err := database.CheckExist(readDBExecutor, &sql.CheckExistExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if exist {
+		t.Fatalf("%+v\n", errors.New("Delete Error"))
+	}
+
+	err = database.InsertEntity(writeDBExecutor, tableName, []any{student1, student2})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	results, totalCount, err := database.Query(readDBExecutor, &sql.QueryExecuteParams{
+		TableName:  tableName,
+		Conditions: sql.NewConditions().In("id", []string{id1, id2}),
+		OrderBy:    "name ASC",
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(results) != 2 || totalCount != 2 {
+		t.Fatalf("%+v\n", errors.Errorf("Insert Batch Error: %v", results))
+	}
+
+	if results[0].ColumnValueString("id") != id1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id1, result.ColumnValueString("id")))
+	}
+
+	if results[0].ColumnValueString("name") != name1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name1, result.ColumnValueString("name")))
+	}
+
+	if results[0].ColumnValueInt32("age") != age1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age1, result.ColumnValueInt32("age")))
+	}
+
+	if results[0].ColumnValueTime("enter_time").Format(time.DateTime) != enterTime1.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime1, result.ColumnValueTime("enter_time")))
+	}
+
+	if results[1].ColumnValueString("id") != id2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id2, result.ColumnValueString("id")))
+	}
+
+	if results[1].ColumnValueString("name") != name2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name2, result.ColumnValueString("name")))
+	}
+
+	if results[1].ColumnValueInt32("age") != age2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age2, result.ColumnValueInt32("age")))
+	}
+
+	if results[1].ColumnValueTime("enter_time").Format(time.DateTime) != enterTime2.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime2, result.ColumnValueTime("enter_time")))
+	}
+
+	hasOnlyOne, err := database.CheckHasOnlyOne(readDBExecutor, &sql.CheckHasOnlyOneExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if !hasOnlyOne {
+		t.Fatalf("%+v\n", errors.New("Check HasOnlyOne Error"))
+	}
+
+	count, err := database.Count(readDBExecutor, &sql.CountExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id2),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if count != 1 {
+		t.Fatalf("%+v\n", errors.New("Count Error"))
+	}
+}
+
+func testDatabase(t *testing.T, writeDBExecutor database.Executor, readDBExecutor database.Executor) {
+	tableName := "test.students"
+
+	id1 := strutils.SimpleUUID()
+	name1 := "1" + strutils.SimpleUUID()
+	age1 := rand.Int31()
+	enterTime1 := time.Now().Local()
+
+	id2 := strutils.SimpleUUID()
+	name2 := "2" + strutils.SimpleUUID()
+	age2 := rand.Int31()
+	enterTime2 := time.Now().Local()
+
+	tableRow1 := sql.NewTableRow().
+		Add("id", id1).
+		Add("name", name1).
+		Add("age", age1).
+		Add("enter_time", enterTime1)
+
+	newTableRow1 := sql.NewTableRow().
+		Add("name", name2).
+		Add("age", age2).
+		Add("enter_time", enterTime2)
+
+	tableRow2 := sql.NewTableRow().
+		Add("id", id2).
+		Add("name", name2).
+		Add("age", age2).
+		Add("enter_time", enterTime2)
+
+	err := database.Insert(writeDBExecutor, &sql.InsertExecuteParams{
+		TableName: tableName,
+		TableRow:  tableRow1,
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	result, err := database.QueryOne(readDBExecutor, &sql.QueryOneExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if result.ColumnValueString("id") != id1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id1, result.ColumnValueString("id")))
+	}
+
+	if result.ColumnValueString("name") != name1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name1, result.ColumnValueString("name")))
+	}
+
+	if result.ColumnValueInt32("age") != age1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age1, result.ColumnValueInt32("age")))
+	}
+
+	if result.ColumnValueTime("enter_time").Format(time.DateTime) != enterTime1.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime1, result.ColumnValueTime("enter_time")))
+	}
+
+	err = database.Update(writeDBExecutor, &sql.UpdateExecuteParams{
+		TableName:  tableName,
+		TableRow:   newTableRow1,
+		Conditions: sql.NewConditions().Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	result, err = database.QueryOne(readDBExecutor, &sql.QueryOneExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if result.ColumnValueString("id") != id1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id1, result.ColumnValueString("id")))
+	}
+
+	if result.ColumnValueString("name") != name2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name2, result.ColumnValueString("name")))
+	}
+
+	if result.ColumnValueInt32("age") != age2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age2, result.ColumnValueInt32("age")))
+	}
+
+	if result.ColumnValueTime("enter_time").Format(time.DateTime) != enterTime2.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime2, result.ColumnValueTime("enter_time")))
+	}
+
+	err = database.Delete(writeDBExecutor, &sql.DeleteExecuteParams{
+		TableName:  tableName,
+		Conditions: sql.NewConditions().Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	exist, err := database.CheckExist(readDBExecutor, &sql.CheckExistExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if exist {
+		t.Fatalf("%+v\n", errors.New("Delete Error"))
+	}
+
+	err = database.InsertBatch(writeDBExecutor, &sql.InsertBatchExecuteParams{
+		TableName:     tableName,
+		TableRowBatch: []sql.TableRow{*tableRow1, *tableRow2},
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	results, totalCount, err := database.Query(readDBExecutor, &sql.QueryExecuteParams{
+		TableName:  tableName,
+		Conditions: sql.NewConditions().In("id", []string{id1, id2}),
+		OrderBy:    "name ASC",
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if len(results) != 2 || totalCount != 2 {
+		t.Fatalf("%+v\n", errors.Errorf("Insert Batch Error: %v", results))
+	}
+
+	if results[0].ColumnValueString("id") != id1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id1, result.ColumnValueString("id")))
+	}
+
+	if results[0].ColumnValueString("name") != name1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name1, result.ColumnValueString("name")))
+	}
+
+	if results[0].ColumnValueInt32("age") != age1 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age1, result.ColumnValueInt32("age")))
+	}
+
+	if results[0].ColumnValueTime("enter_time").Format(time.DateTime) != enterTime1.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime1, result.ColumnValueTime("enter_time")))
+	}
+
+	if results[1].ColumnValueString("id") != id2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			id2, result.ColumnValueString("id")))
+	}
+
+	if results[1].ColumnValueString("name") != name2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			name2, result.ColumnValueString("name")))
+	}
+
+	if results[1].ColumnValueInt32("age") != age2 {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			age2, result.ColumnValueInt32("age")))
+	}
+
+	if results[1].ColumnValueTime("enter_time").Format(time.DateTime) != enterTime2.Format(time.DateTime) {
+		t.Fatalf("%+v\n", errors.Errorf("Result Error: except: %v, actual: %v",
+			enterTime2, result.ColumnValueTime("enter_time")))
+	}
+
+	hasOnlyOne, err := database.CheckHasOnlyOne(readDBExecutor, &sql.CheckHasOnlyOneExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id1),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if !hasOnlyOne {
+		t.Fatalf("%+v\n", errors.New("Check HasOnlyOne Error"))
+	}
+
+	count, err := database.Count(readDBExecutor, &sql.CountExecuteParams{
+		TableName: tableName,
+		Conditions: sql.NewConditions().
+			Equal("id", id2),
+	})
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	if count != 1 {
+		t.Fatalf("%+v\n", errors.New("Count Error"))
+	}
+}