Explorar o código

完成insertk开发,需要统一接口,支持事务和sdk

yjp hai 1 ano
pai
achega
234e730eaf
Modificáronse 4 ficheiros con 169 adicións e 11 borrados
  1. 102 7
      sdk/crud.go
  2. 17 2
      sdk/tag/sql_mapping.go
  3. 17 2
      sdk/tag/sql_result.go
  4. 33 0
      test/sdk_test.go

+ 102 - 7
sdk/crud.go

@@ -1,13 +1,36 @@
 package sdk
 
 import (
+	"errors"
+	"git.sxidc.com/go-tools/utils/strutils"
 	"git.sxidc.com/service-supports/ds-sdk/sdk/raw_sql_tpl"
 	"git.sxidc.com/service-supports/ds-sdk/sdk/tag"
+	"reflect"
+	"strconv"
+	"time"
 )
 
-type InsertCallback[T any] func(e T)
+const (
+	timeWriteFormat          = time.DateTime + ".000000 +08:00"
+	createdTimeFieldName     = "CreatedTime"
+	lastUpdatedTimeFieldName = "LastUpdatedTime"
+)
+
+type InsertCallback[T any] func(e T, fieldName string, value any) (retValue any, err error)
 
 func Insert[T any](sdk *SDK, tableName string, e T, callback InsertCallback[T]) error {
+	if sdk == nil {
+		return errors.New("没有传递sdk")
+	}
+
+	if strutils.IsStringEmpty(tableName) {
+		return errors.New("没有传递表名")
+	}
+
+	if reflect.TypeOf(e) == nil {
+		return errors.New("没有传递实体")
+	}
+
 	sqlMapping, err := tag.ParseSqlMapping(e)
 	if err != nil {
 		return err
@@ -17,20 +40,92 @@ func Insert[T any](sdk *SDK, tableName string, e T, callback InsertCallback[T])
 		TableName: tableName,
 	}
 
-	for column, sqlMappingColumn := range sqlMapping.ColumnMap {
+	now := time.Now()
+
+	for fieldName, sqlMappingColumn := range sqlMapping.ColumnMap {
+		fieldType := sqlMappingColumn.FieldType
+
+		value := reflect.Zero(fieldType).Interface()
+		if !sqlMappingColumn.FieldValue.IsZero() {
+			value = sqlMappingColumn.FieldValue.Interface()
+		}
+
 		if sqlMappingColumn.InsertCallback {
-			if callback != nil {
-				//callback(column)
+			if callback == nil {
+				return errors.New("需要使用回调函数但是没有传递回调函数")
+			}
+
+			retValue, err := callback(e, fieldName, value)
+			if err != nil {
+				return err
+			}
+
+			retValueType := reflect.TypeOf(retValue)
+			if retValueType == nil || retValueType.Kind() == reflect.Ptr {
+				return errors.New("返回应当为值类型")
 			}
+
+			value = retValue
+		}
+
+		if (fieldName == createdTimeFieldName || fieldName == lastUpdatedTimeFieldName) &&
+			fieldType.String() == "time.Time" && value.(time.Time).IsZero() {
+			value = now
+		}
+
+		tableRowValue, err := parseValue(value)
+		if err != nil {
+			return err
 		}
 
 		executeParams.TableRows = append(executeParams.TableRows, raw_sql_tpl.TableRow{
-			Column: column,
-			Value:  "",
+			Column: sqlMappingColumn.Name,
+			Value:  tableRowValue,
 		})
 	}
 
-	//sdk.ExecuteRawSql(raw_sql_tpl.InsertTpl, executeParams)
+	executeParamsMap, err := executeParams.Map()
+	if err != nil {
+		return err
+	}
+
+	_, err = sdk.ExecuteRawSql(raw_sql_tpl.InsertTpl, executeParamsMap)
+	if err != nil {
+		return err
+	}
 
 	return nil
 }
+
+func parseValue(value any) (string, error) {
+	switch v := value.(type) {
+	case string:
+		return "'" + v + "'", nil
+	case bool:
+		return strconv.FormatBool(v), nil
+	case time.Time:
+		return "'" + v.Format(timeWriteFormat) + "'", nil
+	case int:
+		return strconv.Itoa(v), nil
+	case int8:
+		return strconv.FormatInt(int64(v), 10), nil
+	case int16:
+		return strconv.FormatInt(int64(v), 10), nil
+	case int32:
+		return strconv.FormatInt(int64(v), 10), nil
+	case int64:
+		return strconv.FormatInt(v, 10), nil
+	case uint:
+		return strconv.FormatUint(uint64(v), 10), nil
+	case uint8:
+		return strconv.FormatUint(uint64(v), 10), nil
+	case uint16:
+		return strconv.FormatUint(uint64(v), 10), nil
+	case uint32:
+		return strconv.FormatUint(uint64(v), 10), nil
+	case uint64:
+		return strconv.FormatUint(v, 10), nil
+	default:
+		return "", errors.New("不支持的类型")
+	}
+}

+ 17 - 2
sdk/tag/sql_mapping.go

@@ -73,7 +73,6 @@ func ParseSqlMapping(e any) (*SqlMapping, error) {
 
 type SqlMappingColumn struct {
 	Name           string
-	Value          any
 	IsKey          bool
 	CanUpdate      bool
 	CanUpdateClear bool
@@ -81,12 +80,26 @@ type SqlMappingColumn struct {
 	InsertCallback bool
 	UpdateCallback bool
 	QueryCallback  bool
+
+	// 值类型的反射结构
+	FieldType  reflect.Type
+	FieldValue reflect.Value
 }
 
 func parseSqlMappingColumn(field reflect.StructField, fieldValue reflect.Value) (*SqlMappingColumn, error) {
+	fieldType := field.Type
+	if fieldType.Kind() == reflect.Ptr {
+		fieldType = fieldType.Elem()
+
+		if fieldValue.IsZero() {
+			fieldValue = reflect.Zero(fieldType)
+		} else {
+			fieldValue = fieldValue.Elem()
+		}
+	}
+
 	sqlColumn := &SqlMappingColumn{
 		Name:           strcase.ToSnake(field.Name),
-		Value:          fieldValue.Interface(),
 		IsKey:          false,
 		CanUpdate:      true,
 		CanUpdateClear: false,
@@ -94,6 +107,8 @@ func parseSqlMappingColumn(field reflect.StructField, fieldValue reflect.Value)
 		InsertCallback: false,
 		UpdateCallback: false,
 		QueryCallback:  false,
+		FieldType:      fieldType,
+		FieldValue:     fieldValue,
 	}
 
 	sqlMappingTag, ok := field.Tag.Lookup(sqlMappingTagKey)

+ 17 - 2
sdk/tag/sql_result.go

@@ -67,17 +67,32 @@ func ParseSqlResult(e any) (*SqlResult, error) {
 
 type SqlResultColumn struct {
 	Name             string
-	Value            any
 	ResultColumnName string
 	Callback         bool
+
+	// 值类型的反射结构
+	FieldType  reflect.Type
+	FieldValue reflect.Value
 }
 
 func parseSqlResultColumn(field reflect.StructField, fieldValue reflect.Value) (*SqlResultColumn, error) {
+	fieldType := field.Type
+	if fieldType.Kind() == reflect.Ptr {
+		fieldType = fieldType.Elem()
+
+		if fieldValue.IsZero() {
+			fieldValue = reflect.Zero(fieldType)
+		} else {
+			fieldValue = fieldValue.Elem()
+		}
+	}
+
 	sqlColumn := &SqlResultColumn{
 		Name:             strcase.ToSnake(field.Name),
-		Value:            fieldValue.Interface(),
 		ResultColumnName: strcase.ToSnake(field.Name),
 		Callback:         false,
+		FieldType:        fieldType,
+		FieldValue:       fieldValue,
 	}
 
 	sqlResultTag, ok := field.Tag.Lookup(sqlResultTagKey)

+ 33 - 0
test/sdk_test.go

@@ -480,3 +480,36 @@ func TestSqlResult(t *testing.T) {
 		}
 	}
 }
+
+func TestCRUD(t *testing.T) {
+	err := sdk.InitInstance(token, address, httpPort, grpcPort, namespace, dataSource)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	defer func() {
+		err := sdk.DestroyInstance()
+		if err != nil {
+			t.Fatal(err)
+		}
+	}()
+
+	classID := strutils.SimpleUUID()
+	className := strutils.SimpleUUID()
+	studentNum := rand.Int31n(100)
+
+	class := &Class{
+		ID:            classID,
+		Name:          className,
+		StudentNum:    int(studentNum),
+		GraduatedTime: time.Now(),
+		Ignored:       "",
+	}
+
+	err = sdk.Insert(sdk.GetInstance(), tableName, class, func(e *Class, fieldName string, value any) (retValue any, err error) {
+		return value, nil
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+}