package main import ( "fmt" "git.sxidc.com/go-tools/utils/strutils" "git.sxidc.com/service-supports/ds-sdk/sdk" "git.sxidc.com/service-supports/ds-sdk/sql" "git.sxidc.com/service-supports/ds-sdk/sql/sql_tpl" "github.com/iancoleman/strcase" "math/rand" "strings" "sync" "testing" "time" ) type Class struct { ID string `mapstructure:"id"` Name string `sqlmapping:"updateClear;" mapstructure:"name"` StudentNum int `sqlmapping:"column:student_num;notUpdate;" mapstructure:"student_num_alias"` GraduatedTime time.Time `mapstructure:"graduated_time"` CreatedTime *time.Time `mapstructure:"created_time"` LastUpdatedTime time.Time `mapstructure:"last_updated_time"` Ignored string `sqlmapping:"-" mapstructure:"-"` } const ( token = "IpTTwAQweh/BP51fz5CzWKQFaXHvZe6ewvk6yOcAOkU=" address = "localhost" httpPort = "10000" grpcPort = "10001" namespace = "ns-sdk-demo" dataSource = "ds-sdk-demo" deleteSql = "delete-sdk-demo" goRoutineCount = 100 tableName = "test.classes" ) var ( sqlSpec = sdk.SqlSpec{ Clauses: "- DELETE FROM {{ .table_name }} WHERE id = '{{ .id }}'", } ) const ( sqlResultTimeMicroFormat = "2006-01-02T15:04:05.000000+08:00" sqlResultTimeMilliFormat = "2006-01-02T15:04:05.000+08:00" sqlResultTimeSecFormat = "2006-01-02T15:04:05+08:00" ) func chooseTimeLayout(timeStr string) string { if strings.HasSuffix(timeStr, ".000000+08:00") { return sqlResultTimeMicroFormat } else if strings.HasSuffix(timeStr, ".000+08:00") { return sqlResultTimeMilliFormat } else { return sqlResultTimeSecFormat } } func TestBasic(t *testing.T) { classID := strutils.SimpleUUID() className := strutils.SimpleUUID() studentNum := rand.Int31n(100) now := time.Now() insertExecuteParams, err := sql_tpl.InsertExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("id", classID). Add("name", className). Add("student_num", studentNum). Add("graduated_time", now). Add("created_time", now). Add("last_updated_time", now), }.Map() if err != nil { t.Fatal(err) } deleteExecuteParams := map[string]any{ "table_name": tableName, "id": classID, } 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) } }() err = sdk.GetInstance().CreateSQL(deleteSql, sqlSpec.ToMap()) if err != nil { t.Fatal(err) } defer func() { err = sdk.GetInstance().DeleteSQL(deleteSql) if err != nil { t.Fatal(err) } }() _, err = sdk.GetInstance().ExecuteRawSql(sql_tpl.InsertTpl, insertExecuteParams) if err != nil { t.Fatal(err) } _, err = sdk.GetInstance().ExecuteSql(deleteSql, deleteExecuteParams) if err != nil { t.Fatal(err) } wg := sync.WaitGroup{} wg.Add(goRoutineCount) start := time.Now() for i := 0; i < goRoutineCount; i++ { go func() { defer wg.Done() err = sdk.GetInstance().Transaction(func(tx *sdk.Transaction) error { _, err := tx.ExecuteRawSql(sql_tpl.InsertTpl, insertExecuteParams) if err != nil { return err } _, err = tx.ExecuteSql(deleteSql, deleteExecuteParams) if err != nil { return err } return nil }) if err != nil { panic(err) } }() } wg.Wait() end := time.Now() fmt.Println(end.Sub(start).Milliseconds()) } func TestRawSqlTemplate(t *testing.T) { classID := strutils.SimpleUUID() className := strutils.SimpleUUID() studentNum := rand.Int31n(100) newClassName := strutils.SimpleUUID() newStudentNum := rand.Int31n(100) now := time.Now() insertExecuteParams, err := sql_tpl.InsertExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("id", classID). Add("name", className). Add("student_num", studentNum). Add("graduated_time", now). Add("created_time", now). Add("last_updated_time", now), }.Map() if err != nil { t.Fatal(err) } deleteExecuteParams, err := sql_tpl.DeleteExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions().Equal("id", classID), }.Map() if err != nil { t.Fatal(err) } updateExecuteParams, err := sql_tpl.UpdateExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("name", newClassName). Add("student_num", newStudentNum), Conditions: sql_tpl.NewConditions().Equal("id", classID), }.Map() if err != nil { t.Fatal(err) } queryExecuteParams, err := sql_tpl.QueryExecuteParams{ TableName: tableName, SelectColumns: []string{"id", "name", "student_num as student_num_alias", "graduated_time", "created_time", "last_updated_time"}, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", className). Equal("student_num", studentNum), PageNo: 1, PageSize: 1, }.Map() if err != nil { t.Fatal(err) } newQueryExecuteParams, err := sql_tpl.QueryExecuteParams{ TableName: tableName, SelectColumns: []string{"id", "name", "student_num as student_num_alias", "graduated_time", "created_time", "last_updated_time"}, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", newClassName). Equal("student_num", newStudentNum), PageNo: 0, PageSize: 0, }.Map() if err != nil { t.Fatal(err) } countExecuteParams, err := sql_tpl.CountExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", className). Equal("student_num", studentNum), }.Map() if err != nil { t.Fatal(err) } newCountExecuteParams, err := sql_tpl.CountExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", newClassName). Equal("student_num", newStudentNum), }.Map() if err != nil { t.Fatal(err) } 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) } }() _, err = sdk.GetInstance().ExecuteRawSql(sql_tpl.InsertTpl, insertExecuteParams) if err != nil { t.Fatal(err) } queryResults, err := sdk.GetInstance().ExecuteRawSql(sql_tpl.QueryTpl, queryExecuteParams) if err != nil { t.Fatal(err) } countResults, err := sdk.GetInstance().ExecuteRawSql(sql_tpl.CountTpl, countExecuteParams) if err != nil { t.Fatal(err) } classes := make([]Class, 0) err = sql.ParseSqlResults(queryResults, &classes) if err != nil { t.Fatal(err) } if float64(len(classes)) != countResults[0]["count"].(float64) { t.Fatal("总数不正确") } graduatedTimeLayout := chooseTimeLayout(queryResults[0]["graduated_time"].(string)) createdTimeLayout := chooseTimeLayout(queryResults[0]["created_time"].(string)) lastUpdatedTimeLayout := chooseTimeLayout(queryResults[0]["last_updated_time"].(string)) if classes[0].ID != classID || classes[0].Name != className || classes[0].StudentNum != int(studentNum) || classes[0].GraduatedTime.Format(graduatedTimeLayout) != now.Format(graduatedTimeLayout) || classes[0].CreatedTime.Format(createdTimeLayout) != now.Format(createdTimeLayout) || classes[0].LastUpdatedTime.Format(lastUpdatedTimeLayout) != now.Format(lastUpdatedTimeLayout) { t.Fatal("查询数据不正确") } _, err = sdk.GetInstance().ExecuteRawSql(sql_tpl.UpdateTpl, updateExecuteParams) if err != nil { t.Fatal(err) } queryResults, err = sdk.GetInstance().ExecuteRawSql(sql_tpl.QueryTpl, newQueryExecuteParams) if err != nil { t.Fatal(err) } countResults, err = sdk.GetInstance().ExecuteRawSql(sql_tpl.CountTpl, newCountExecuteParams) if err != nil { t.Fatal(err) } classes = make([]Class, 0) err = sql.ParseSqlResults(queryResults, &classes) if err != nil { t.Fatal(err) } if float64(len(classes)) != countResults[0]["count"].(float64) { t.Fatal("总数不正确") } graduatedTimeLayout = chooseTimeLayout(queryResults[0]["graduated_time"].(string)) createdTimeLayout = chooseTimeLayout(queryResults[0]["created_time"].(string)) lastUpdatedTimeLayout = chooseTimeLayout(queryResults[0]["last_updated_time"].(string)) if classes[0].ID != classID || classes[0].Name != newClassName || classes[0].StudentNum != int(newStudentNum) || classes[0].GraduatedTime.Format(graduatedTimeLayout) != now.Format(graduatedTimeLayout) || classes[0].CreatedTime.Format(createdTimeLayout) != now.Format(createdTimeLayout) || classes[0].LastUpdatedTime.Format(lastUpdatedTimeLayout) != now.Format(lastUpdatedTimeLayout) { t.Fatal("查询数据不正确") } _, err = sdk.GetInstance().ExecuteRawSql(sql_tpl.DeleteTpl, deleteExecuteParams) if err != nil { t.Fatal(err) } } func TestSqlMapping(t *testing.T) { sqlMapping, err := sql.ParseSqlMapping(&Class{}) if err != nil { t.Fatal(err) } for fieldName, sqlColumn := range sqlMapping.ColumnMap { if fieldName != "ID" && fieldName != "Name" && fieldName != "StudentNum" && fieldName != "GraduatedTime" && fieldName != "CreatedTime" && fieldName != "LastUpdatedTime" { t.Fatal("字段名不正确") } if sqlColumn.Name != "id" && sqlColumn.Name != "name" && sqlColumn.Name != "student_num" && sqlColumn.Name != "graduated_time" && sqlColumn.Name != "created_time" && sqlColumn.Name != "last_updated_time" { t.Fatal("列名不正确") } if sqlColumn.Name != strcase.ToSnake(fieldName) { t.Fatal("列名不正确") } if sqlColumn.IsKey && sqlColumn.Name != "id" { t.Fatal("键字段不正确") } if !sqlColumn.CanUpdate && (sqlColumn.Name != "id" && sqlColumn.Name != "student_num") { t.Fatal("不可更新字段不正确") } if sqlColumn.CanUpdateClear && sqlColumn.Name != "name" { t.Fatal("可清除字段不正确") } } } func TestSql(t *testing.T) { classID := strutils.SimpleUUID() className := strutils.SimpleUUID() studentNum := rand.Int31n(100) newClassName := strutils.SimpleUUID() newStudentNum := rand.Int31n(100) now := time.Now() insertExecuteParams, err := sql_tpl.InsertExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("id", classID). Add("name", className). Add("student_num", studentNum). Add("graduated_time", now). Add("created_time", now). Add("last_updated_time", now), }.Map() if err != nil { t.Fatal(err) } deleteExecuteParams := map[string]any{ "table_name": tableName, "id": classID, } class := &Class{ ID: classID, Name: className, StudentNum: int(studentNum), GraduatedTime: time.Now(), Ignored: "", } newClass := &Class{ ID: classID, Name: newClassName, StudentNum: int(newStudentNum), GraduatedTime: time.Now(), Ignored: "", } queryClasses := make([]Class, 0) queryClass := new(Class) 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) } }() err = sdk.GetInstance().CreateSQL(deleteSql, sqlSpec.ToMap()) if err != nil { t.Fatal(err) } defer func() { err = sdk.GetInstance().DeleteSQL(deleteSql) if err != nil { t.Fatal(err) } }() err = sql.InsertEntity(sdk.GetInstance(), tableName, class) if err != nil { t.Fatal(err) } err = sql.UpdateEntity(sdk.GetInstance(), tableName, newClass) if err != nil { t.Fatal(err) } err = sql.DeleteEntity(sdk.GetInstance(), tableName, class) if err != nil { t.Fatal(err) } err = sql.Insert(sdk.GetInstance(), &sql_tpl.InsertExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("id", classID). Add("name", className). Add("student_num", studentNum). Add("graduated_time", now). Add("created_time", now). Add("last_updated_time", now), }) if err != nil { t.Fatal(err) } err = sql.Update(sdk.GetInstance(), &sql_tpl.UpdateExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("id", classID). Add("name", newClassName). Add("student_num", newStudentNum), Conditions: sql_tpl.NewConditions(). Equal("id", classID), }) if err != nil { t.Fatal(err) } err = sql.Delete(sdk.GetInstance(), &sql_tpl.DeleteExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions(). Equal("id", classID), }) if err != nil { t.Fatal(err) } _, err = sql.ExecuteRawSql(sdk.GetInstance(), sql_tpl.InsertTpl, insertExecuteParams) if err != nil { t.Fatal(err) } _, err = sql.ExecuteSql(sdk.GetInstance(), deleteSql, deleteExecuteParams) if err != nil { t.Fatal(err) } err = sdk.GetInstance().Transaction(func(tx *sdk.Transaction) error { err = sql.InsertEntity(tx, tableName, class) if err != nil { t.Fatal(err) } err = sql.UpdateEntity(tx, tableName, newClass) if err != nil { t.Fatal(err) } err = sql.DeleteEntity(tx, tableName, class) if err != nil { t.Fatal(err) } err = sql.Insert(tx, &sql_tpl.InsertExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("id", classID). Add("name", className). Add("student_num", studentNum). Add("graduated_time", now). Add("created_time", now). Add("last_updated_time", now), }) if err != nil { t.Fatal(err) } err = sql.Update(tx, &sql_tpl.UpdateExecuteParams{ TableName: tableName, TableRows: sql_tpl.NewTableRows().Add("id", classID). Add("name", newClassName). Add("student_num", newStudentNum), Conditions: sql_tpl.NewConditions(). Equal("id", classID), }) if err != nil { t.Fatal(err) } err = sql.Delete(tx, &sql_tpl.DeleteExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions(). Equal("id", classID), }) if err != nil { t.Fatal(err) } _, err = sql.ExecuteRawSql(tx, sql_tpl.InsertTpl, insertExecuteParams) if err != nil { t.Fatal(err) } _, err = sql.ExecuteSql(tx, deleteSql, deleteExecuteParams) if err != nil { t.Fatal(err) } return nil }) if err != nil { t.Fatal(err) } err = sql.InsertEntity(sdk.GetInstance(), tableName, class) if err != nil { t.Fatal(err) } tableRows, totalCount, err := sql.Query(sdk.GetInstance(), &sql_tpl.QueryExecuteParams{ TableName: tableName, SelectColumns: []string{"id", "name"}, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", className). Equal("student_num", studentNum), PageNo: 0, PageSize: 0, }) if err != nil { t.Fatal(err) } if totalCount != 1 || len(tableRows) != int(totalCount) { t.Fatal("总数不正确") } err = sql.ParseSqlResults(tableRows, &queryClasses) if err != nil { t.Fatal(err) } if queryClasses[0].ID != classID || queryClasses[0].Name != className || queryClasses[0].StudentNum != 0 || !queryClasses[0].GraduatedTime.IsZero() || (queryClasses[0].CreatedTime != nil && !queryClasses[0].CreatedTime.IsZero()) || !queryClasses[0].LastUpdatedTime.IsZero() { t.Fatal("查询数据不正确") } tableRow, err := sql.QueryOne(sdk.GetInstance(), &sql_tpl.QueryOneExecuteParams{ TableName: tableName, SelectColumns: []string{"id", "name"}, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", className). Equal("student_num", studentNum), }) if err != nil { t.Fatal(err) } err = sql.ParseSqlResults(tableRow, queryClass) if err != nil { t.Fatal(err) } if queryClass.ID != classID || queryClass.Name != className || queryClass.StudentNum != 0 || !queryClass.GraduatedTime.IsZero() || (queryClass.CreatedTime != nil && !queryClass.CreatedTime.IsZero()) || !queryClass.LastUpdatedTime.IsZero() { t.Fatal("查询数据不正确") } queryCount, err := sql.Count(sdk.GetInstance(), &sql_tpl.CountExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", className). Equal("student_num", studentNum), }) if err != nil { t.Fatal(err) } if queryCount != 1 { t.Fatal("数量不正确") } exist, err := sql.CheckExist(sdk.GetInstance(), &sql_tpl.CheckExistExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", className). Equal("student_num", studentNum), }) if err != nil { t.Fatal(err) } if !exist { t.Fatal("存在状态错误") } hasOnlyOne, err := sql.CheckHasOnlyOne(sdk.GetInstance(), &sql_tpl.CheckHasOnlyOneExecuteParams{ TableName: tableName, Conditions: sql_tpl.NewConditions(). Equal("id", classID). Equal("name", className). Equal("student_num", studentNum), }) if err != nil { t.Fatal(err) } if !hasOnlyOne { t.Fatal("唯一性错误") } err = sql.DeleteEntity(sdk.GetInstance(), tableName, class) if err != nil { t.Fatal(err) } }