diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c4a14cb --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +test: + go test ./... -v macro diff --git a/README.md b/README.md index fcd3f68..b22302b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # tools [![Go Report Card](https://goreportcard.com/badge/github.com/fishedee/tools)](https://goreportcard.com/report/github.com/fishedee/tools) -[![GoDoc](https://godoc.org/github.com/fishedee/tools?status.svg)](https://godoc.org/github.com/fishedee/tools) +[![GoDoc](https://pkg.go.dev/github.com/fishedee/tools?status.svg)](https://pkg.go.dev/github.com/fishedee/tools) Efficient and convenient func for golang data processing.All original code comes from [here](https://github.com/fishedee/fishgo/tree/master/src/github.com/fishedee/language). Chinese read [这里](README_zhCN.md) +**This library already supports Go1.18 generic.** + ## Why ```golang @@ -18,14 +20,14 @@ sort.Slice(people, func(i, j int) bool { When we write backend code,we often extract data from database.and next step ,we need to group,join and sort multiple table data to generate result in golang service.The code like this is always repeat again and again, The code we write more,The boring we feel more. ```golang -pepole2 := query.Sort(people,"Age asc").([]People) +pepole2 := query.Sort(people,"Age asc") ``` so we have an idea!we use a unify API to finish group,join and sort.but because of strong typed in golang,we only use interface{} to handle different type input data,and use reflect to achieve the algorithm. as we finish this tool , it is a new world for me,the code more short,more easy and more beautiful.And after a period of time, we find a new problem,when we handle one million rows in this API,it will slow.This is a simple reason,because all algorithm is achieved by reflect, not by hand.Compiler can not optimize the code by different type.The other reason is there are much time wasted in reflect package by type get and type check. ```golang -func querySortV10a439a196b4cc9dca0592a40a23aba8392203e4(data interface{}, sortType string) interface{} { - dataIn := data.([]People) +func querySortV10a439a196b4cc9dca0592a40a23aba8392203e4(data []People, sortType string) []People { + dataIn := data newData := make([]People, len(dataIn), len(dataIn)) copy(newData, dataIn) @@ -50,7 +52,7 @@ So when we run query.Sort(xxxx),query.Sort will find the "concrete sort code" by ```sh -gen -r packageName +gen -r [packageName] # specify package,if not, use current package ``` all of this ,we only need to run this command before we compile.That is all. @@ -100,82 +102,82 @@ var admins = make([]Admin, 1000, 1000) // extract column from table // * First Argument:table // * Second Argument:column name -result := query.Column(users, "UserID") -userIDs := result.([]int) +userIDs := query.Column[User, int](users, "UserID") // []int // generate a map from table,key is column value and value is it's row // * First Argument:table // * Second Argument:column name -result = query.ColumnMap(users, "UserID") -userMap := result.(map[int]User) +userMap = query.ColumnMap[User, int, map[int]User](users, "UserID") // map[int]User +// or +usersMap = query.ColumnMap[User, int, map[int][]User](users, "[]UserID") // map[int][]User // select data from table // * First Argument:table // * Second Argument:select rule -result = query.Select(users, func(a User) Sex { +sel = query.Select(users, func(a User) Sex { if len(a.Name) >= 3 && a.Name[0:3] == "Man" { return Sex{IsMale: true} } return Sex{IsMale: false} -}) -sel := result.([]Sex) +}) // []Sex // filter data from table // * First Argument:table // * Second Argument:filter rule -result = query.Where(users, func(a User) bool { +where = query.Where(users, func(a User) bool { if len(a.Name) >= 3 && a.Name[0:3] == "Man" { return true } return false -}) -where := result.([]User) +}) // []User // combine data from two table , one by one // * First Argument:left table // * Second Argument:right table // * Third Argument:combine rule -result = query.Combine(admins, users, func(admin Admin, user User) AdminUser { +combine = query.Combine(admins, users, func(admin Admin, user User) AdminUser { return AdminUser{ AdminID: admin.AdminID, Level: admin.Level, Name: user.Name, CreateTime: user.CreateTime, } -}) -combine := result.([]AdminUser) +}) // []AdminUser // group data from table // * First Argument: left table // * Second Argument: group column name // * Third Argument: group rule -result = query.Group(users, "UserID", func(users []User) Department { +group = query.Group[User, Department, []Department](users, "UserID", func(users []User) Department { return Department{ Employees: users, } -}) -group := result.([]Department) +}) // []Department +// or +group = query.Group[User, []Department, *[]Department](users, "UserID", func(users []User) []Department { + return []Department{ + Employees: users, + } +}) // *[]Department // join data from two table,support LeftJoin,RightJoin,InnerJoin和OuterJoin // * First Argument: left table // * Second Argument: right table // * Third Argument: join condition // * Forth Argument: join rule -result = query.LeftJoin(admins, users, "AdminID = UserID", func(admin Admin, user User) AdminUser { +join = query.LeftJoin(admins, users, "AdminID = UserID", func(admin Admin, user User) AdminUser { return AdminUser{ AdminID: admin.AdminID, Level: admin.Level, Name: user.Name, CreateTime: user.CreateTime, } -}) -join := result.([]AdminUser) +}) // []AdminUser // sort data from table,support multiple column,for Example: UserId desc,Age asc // * First Argument:table // * Second Argument:sort condition -result = query.Sort(users, "UserID asc") -sort := result.([]User) +sort = query.Sort(users, "UserID asc") // []User ``` This is All API , easy and less @@ -187,7 +189,7 @@ Install: go install github.com/fishedee/tools/cmd/gen Use: -gen -r PackageName +gen -r [PackageName] # can ignore PackageName, when do that, use the current package ``` gen is the core of hight performance, it is easy to use , gen and packageName. If you add -r argument , it will read all code in children package(include children of children package, and so on).when gen tool read all code ,it will analyse where call query.XXXXX, and it will auto generate a file named xxxx_querygen.go in the same package.At last, compile all the code just as common and it work! @@ -195,39 +197,76 @@ gen is the core of hight performance, it is easy to use , gen and packageName. I NOTICE,if you change the code in package , you should run gen tool again. ``` -BenchmarkQueryColumnHand-8 200000 5297 ns/op 8192 B/op 1 allocs/op -BenchmarkQueryColumnMacro-8 300000 5223 ns/op 8256 B/op 3 allocs/op -BenchmarkQueryColumnReflect-8 50000 38013 ns/op 8320 B/op 5 allocs/op - -BenchmarkQueryColumnMapHand-8 20000 66341 ns/op 147488 B/op 2 allocs/op -BenchmarkQueryColumnMapMacro-8 20000 66511 ns/op 147568 B/op 4 allocs/op -BenchmarkQueryColumnMapReflect-8 5000 239529 ns/op 314034 B/op 39 allocs/op - -BenchmarkQueryCombineHand-8 50000 26340 ns/op 65536 B/op 1 allocs/op -BenchmarkQueryCombineMacro-8 50000 37597 ns/op 65632 B/op 4 allocs/op -BenchmarkQueryCombineReflect-8 5000 371373 ns/op 241632 B/op 2004 allocs/op - -BenchmarkQueryGroupHand-8 10000 174619 ns/op 195104 B/op 1003 allocs/op -BenchmarkQueryGroupMacro-8 20000 105002 ns/op 155866 B/op 11 allocs/op -BenchmarkQueryGroupReflect-8 2000 589985 ns/op 332019 B/op 4016 allocs/op - -BenchmarkQueryJoinHand-8 10000 221373 ns/op 264036 B/op 1031 allocs/op -BenchmarkQueryJoinMacro-8 10000 123249 ns/op 157075 B/op 18 allocs/op -BenchmarkQueryJoinReflect-8 2000 748088 ns/op 430941 B/op 3039 allocs/op - -BenchmarkQuerySelectHand-8 500000 3354 ns/op 1024 B/op 1 allocs/op -BenchmarkQuerySelectMacro-8 300000 5402 ns/op 1088 B/op 3 allocs/op -BenchmarkQuerySelectReflect-8 5000 286608 ns/op 97088 B/op 2003 allocs/op - -BenchmarkQuerySortHand-8 2000 877680 ns/op 57488 B/op 4 allocs/op -BenchmarkQuerySortMacro-8 3000 403047 ns/op 57536 B/op 8 allocs/op -BenchmarkQuerySortReflect-8 1000 1332166 ns/op 57952 B/op 22 allocs/op +goos: linux +goarch: amd64 +pkg: github.com/fishedee/tools/cmd/gen +cpu: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz + +BenchmarkQueryColumnHand +BenchmarkQueryColumnHand-4 215596 4776 ns/op 8192 B/op 1 allocs/op +BenchmarkQueryColumnMacro +BenchmarkQueryColumnMacro-4 214627 4770 ns/op 8216 B/op 2 allocs/op +BenchmarkQueryColumnReflect +BenchmarkQueryColumnReflect-4 50305 23254 ns/op 8296 B/op 5 allocs/op + +BenchmarkQueryColumnMapHand +BenchmarkQueryColumnMapHand-4 17434 72615 ns/op 147480 B/op 2 allocs/op +BenchmarkQueryColumnMapMacro +BenchmarkQueryColumnMapMacro-4 17889 71254 ns/op 147552 B/op 4 allocs/op +BenchmarkQueryColumnMapReflect +BenchmarkQueryColumnMapReflect-4 9592 114374 ns/op 147608 B/op 6 allocs/op + +BenchmarkQueryColumnMapSliceHand +BenchmarkQueryColumnMapSliceHand-4 7903 154506 ns/op 145944 B/op 1002 allocs/op +BenchmarkQueryColumnMapSliceMacro +BenchmarkQueryColumnMapSliceMacro-4 6750 151835 ns/op 188649 B/op 12 allocs/op +BenchmarkQueryColumnMapSliceReflect +BenchmarkQueryColumnMapSliceReflect-4 3522 314086 ns/op 212818 B/op 1018 allocs/op + +BenchmarkQueryCombineHand +BenchmarkQueryCombineHand-4 37981 31381 ns/op 65536 B/op 1 allocs/op +BenchmarkQueryCombineMacro +BenchmarkQueryCombineMacro-4 29568 37010 ns/op 65584 B/op 3 allocs/op +BenchmarkQueryCombineReflect +BenchmarkQueryCombineReflect-4 1999 578415 ns/op 177657 B/op 3006 allocs/op + +BenchmarkQueryGroupHand +BenchmarkQueryGroupHand-4 4983 201296 ns/op 195098 B/op 1003 allocs/op +BenchmarkQueryGroupMacro +BenchmarkQueryGroupMacro-4 11942 104433 ns/op 155810 B/op 10 allocs/op +BenchmarkQueryGroupReflect +BenchmarkQueryGroupReflect-4 1810 643851 ns/op 275994 B/op 4017 allocs/op + +BenchmarkQueryJoinHand +BenchmarkQueryJoinHand-4 6081 180254 ns/op 256049 B/op 1031 allocs/op +BenchmarkQueryJoinMacro +BenchmarkQueryJoinMacro-4 7669 132689 ns/op 156995 B/op 17 allocs/op +BenchmarkQueryJoinReflect +BenchmarkQueryJoinReflect-4 1252 805528 ns/op 472557 B/op 4039 allocs/op + +BenchmarkQuerySelectHand +BenchmarkQuerySelectHand-4 360092 3073 ns/op 1024 B/op 1 allocs/op +BenchmarkQuerySelectMacro +BenchmarkQuerySelectMacro-4 204452 5238 ns/op 1048 B/op 2 allocs/op +BenchmarkQuerySelectReflect +BenchmarkQuerySelectReflect-4 3679 301481 ns/op 26096 B/op 2004 allocs/op + +BenchmarkQuerySortHand +BenchmarkQuerySortHand-4 2088 490302 ns/op 57480 B/op 4 allocs/op +BenchmarkQuerySortMacro +BenchmarkQuerySortMacro-4 3784 321839 ns/op 57488 B/op 7 allocs/op +BenchmarkQuerySortReflect +BenchmarkQuerySortReflect-4 1339 833588 ns/op 57848 B/op 20 allocs/op + +BenchmarkQueryWhereHand +BenchmarkQueryWhereHand-4 62037 17216 ns/op 57344 B/op 1 allocs/op +BenchmarkQueryWhereMacro +BenchmarkQueryWhereMacro-4 49932 20469 ns/op 57368 B/op 2 allocs/op +BenchmarkQueryWhereReflect +BenchmarkQueryWhereReflect-4 5196 233892 ns/op 25072 B/op 2003 allocs/op -BenchmarkQueryWhereHand-8 100000 18973 ns/op 57344 B/op 1 allocs/op -BenchmarkQueryWhereMacro-8 100000 19157 ns/op 57408 B/op 3 allocs/op -BenchmarkQueryWhereReflect-8 10000 207993 ns/op 48064 B/op 2002 allocs/op PASS -ok github.com/fishedee/tools/cmd/gen 43.099s +ok github.com/fishedee/tools/cmd/gen 38.660s ``` In Benchmark case , auto generate code is fast as same as hand code. In some specify scence(group,join,sort),auto generate code is two times faster than hand code, because of very optimized algorithm and very careful memory allocate.If you want to know why,you should see the auto generate [code](https://github.com/fishedee/tools/blob/master/query/testdata/testdata_querygen.go) diff --git a/README_zhCN.md b/README_zhCN.md index a98f996..434e0ca 100644 --- a/README_zhCN.md +++ b/README_zhCN.md @@ -1,10 +1,12 @@ # tools [![Go Report Card](https://goreportcard.com/badge/github.com/fishedee/tools)](https://goreportcard.com/report/github.com/fishedee/tools) -[![GoDoc](https://godoc.org/github.com/fishedee/tools?status.svg)](https://godoc.org/github.com/fishedee/tools) +[![GoDoc](https://pkg.go.dev/github.com/fishedee/tools?status.svg)](https://pkg.go.dev/github.com/fishedee/tools) 高性能便利的golang数据操作库,原始代码来源于这里[here](https://github.com/fishedee/fishgo/tree/master/src/github.com/fishedee/language). +**注意, 现已支持Go1.18泛型。** + ## 原理 ```golang @@ -16,14 +18,14 @@ sort.Slice(people, func(i, j int) bool { 因为写后台服务时,经常是从数据库中取出数据,然后我们时常需要对多个表的数据在golang业务层进行group,join,sort等操作。这些操作大同小异,写得多了就感觉重复繁琐,容易出错。 ```golang -pepole2 := query.Sort(people,"Age asc").([]People) +pepole2 := query.Sort(people,"Age asc") ``` 所以我们的想法是模拟数据库的sql操作,在golang上用统一的API来执行group,join,sort等操作。当然,由于golang的强类型特性,我们只能用interface{}来处理不同类型的输入,然后用reflect来实现算法。有了这个工具以后,我们在写业务代码时爽了很多,代码更简洁,更清晰。但是,我们随后发现了这样做对于超大数据量(10w行以上数据)时,会造成比较严重的性能问题。原因很简单,因为操作数据的算法都是用reflect来实现,有大量的时间浪费在reflect的类型解析和校验上了,而且,golang编译器无法像手工写代码一样能在编译时根据不同的代码执行最好的优化。 ```golang -func querySortV10a439a196b4cc9dca0592a40a23aba8392203e4(data interface{}, sortType string) interface{} { - dataIn := data.([]People) +func querySortV10a439a196b4cc9dca0592a40a23aba8392203e4(data []People, sortType string) []People { + dataIn := data newData := make([]People, len(dataIn), len(dataIn)) copy(newData, dataIn) @@ -46,7 +48,7 @@ func querySortV10a439a196b4cc9dca0592a40a23aba8392203e4(data interface{}, sortTy ```sh -gen -r packageName +gen -r [packageName] # 指定包名,不指定则使用当前目录所在包 ``` 而这一切,我们需要做的,仅仅就是在编译前,执行一行命令而已。 @@ -96,82 +98,82 @@ var admins = make([]Admin, 1000, 1000) // 获取指定列 // * 第一个参数为表格 // * 第二个参数为列名 -result := query.Column(users, "UserID") -userIDs := result.([]int) +userIDs := query.Column[User, int](users, "UserID") // []int // 以某列的值生成映射 // * 第一个参数为表格 // * 第二个参数为列名 -result = query.ColumnMap(users, "UserID") -userMap := result.(map[int]User) +userMap = query.ColumnMap[User, int, map[int]User](users, "UserID") // map[int]User +// or +usersMap = query.ColumnMap[User, int, map[int][]User](users, "[]UserID") // map[int][]User // 表格转换或提取操作 // * 第一个参数为表格 // * 第二个参数为转换规则 -result = query.Select(users, func(a User) Sex { +sel = query.Select(users, func(a User) Sex { if len(a.Name) >= 3 && a.Name[0:3] == "Man" { return Sex{IsMale: true} } return Sex{IsMale: false} -}) -sel := result.([]Sex) +}) // []Sex // 表格筛选操作 // * 第一个参数为表格 // * 第二个参数为筛选规则 -result = query.Where(users, func(a User) bool { +where = query.Where(users, func(a User) bool { if len(a.Name) >= 3 && a.Name[0:3] == "Man" { return true } return false -}) -where := result.([]User) +}) // []User // 两个表一对一合并 // * 第一个参数为左表 // * 第二个参数为右表 // * 第三个参数为合并规则 -result = query.Combine(admins, users, func(admin Admin, user User) AdminUser { +combine = query.Combine(admins, users, func(admin Admin, user User) AdminUser { return AdminUser{ AdminID: admin.AdminID, Level: admin.Level, Name: user.Name, CreateTime: user.CreateTime, } -}) -combine := result.([]AdminUser) +}) // []AdminUser // 表根据某列进行分组操作 // * 第一个参数为表格 // * 第二个参数为列名 // * 第三个参数为分组规则 -result = query.Group(users, "UserID", func(users []User) Department { +group = query.Group[User, Department, []Department](users, "UserID", func(users []User) Department { return Department{ Employees: users, } -}) -group := result.([]Department) +}) // []Department +// or +group = query.Group[User, []Department, *[]Department](users, "UserID", func(users []User) []Department { + return []Department{ + Employees: users, + } +}) // *[]Department // 两个表进行连接操作,支持LeftJoin,RightJoin,InnerJoin和OuterJoin // * 第一个参数为左表 // * 第二个参数为右表 // * 第三个参数为连接操作的条件 // * 第四个参数为连接规则 -result = query.LeftJoin(admins, users, "AdminID = UserID", func(admin Admin, user User) AdminUser { +join = query.LeftJoin(admins, users, "AdminID = UserID", func(admin Admin, user User) AdminUser { return AdminUser{ AdminID: admin.AdminID, Level: admin.Level, Name: user.Name, CreateTime: user.CreateTime, } -}) -join := result.([]AdminUser) +}) // []AdminUser // 表格排序操作,支持多列排序,如UserId desc,Age asc // * 第一个参数为表格 // * 第二个参数为排序规则 -result = query.Sort(users, "UserID asc") -sort := result.([]User) +sort = query.Sort(users, "UserID asc") // []User ``` 就以上这几个API,没有其他的了,参数一目了然。 @@ -183,45 +185,82 @@ sort := result.([]User) go install github.com/fishedee/tools/cmd/gen 使用: -gen -r 包名 +gen -r [包名] ``` gen工具是性能提速的核心,使用方法很简单,gen加包名就可以了,如果加-r参数,其会递归查找包下的所有子包的源码。gen读取源码以后,其会自动分析调用query.XXXX的地方,然后就会生成一个xxxx_querygen.go代码来代替reflect的实现。最后,你就能如平常一样编译代码就可以了,就能享受到超便利和高性能的好处了。但要注意的是,当包下面的源代码发生改变后,你要重新执行gen来生成代码。 ``` -BenchmarkQueryColumnHand-8 200000 5297 ns/op 8192 B/op 1 allocs/op -BenchmarkQueryColumnMacro-8 300000 5223 ns/op 8256 B/op 3 allocs/op -BenchmarkQueryColumnReflect-8 50000 38013 ns/op 8320 B/op 5 allocs/op - -BenchmarkQueryColumnMapHand-8 20000 66341 ns/op 147488 B/op 2 allocs/op -BenchmarkQueryColumnMapMacro-8 20000 66511 ns/op 147568 B/op 4 allocs/op -BenchmarkQueryColumnMapReflect-8 5000 239529 ns/op 314034 B/op 39 allocs/op - -BenchmarkQueryCombineHand-8 50000 26340 ns/op 65536 B/op 1 allocs/op -BenchmarkQueryCombineMacro-8 50000 37597 ns/op 65632 B/op 4 allocs/op -BenchmarkQueryCombineReflect-8 5000 371373 ns/op 241632 B/op 2004 allocs/op - -BenchmarkQueryGroupHand-8 10000 174619 ns/op 195104 B/op 1003 allocs/op -BenchmarkQueryGroupMacro-8 20000 105002 ns/op 155866 B/op 11 allocs/op -BenchmarkQueryGroupReflect-8 2000 589985 ns/op 332019 B/op 4016 allocs/op - -BenchmarkQueryJoinHand-8 10000 221373 ns/op 264036 B/op 1031 allocs/op -BenchmarkQueryJoinMacro-8 10000 123249 ns/op 157075 B/op 18 allocs/op -BenchmarkQueryJoinReflect-8 2000 748088 ns/op 430941 B/op 3039 allocs/op - -BenchmarkQuerySelectHand-8 500000 3354 ns/op 1024 B/op 1 allocs/op -BenchmarkQuerySelectMacro-8 300000 5402 ns/op 1088 B/op 3 allocs/op -BenchmarkQuerySelectReflect-8 5000 286608 ns/op 97088 B/op 2003 allocs/op - -BenchmarkQuerySortHand-8 2000 877680 ns/op 57488 B/op 4 allocs/op -BenchmarkQuerySortMacro-8 3000 403047 ns/op 57536 B/op 8 allocs/op -BenchmarkQuerySortReflect-8 1000 1332166 ns/op 57952 B/op 22 allocs/op +goos: linux +goarch: amd64 +pkg: github.com/fishedee/tools/cmd/gen +cpu: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz + +BenchmarkQueryColumnHand +BenchmarkQueryColumnHand-4 215596 4776 ns/op 8192 B/op 1 allocs/op +BenchmarkQueryColumnMacro +BenchmarkQueryColumnMacro-4 214627 4770 ns/op 8216 B/op 2 allocs/op +BenchmarkQueryColumnReflect +BenchmarkQueryColumnReflect-4 50305 23254 ns/op 8296 B/op 5 allocs/op + +BenchmarkQueryColumnMapHand +BenchmarkQueryColumnMapHand-4 17434 72615 ns/op 147480 B/op 2 allocs/op +BenchmarkQueryColumnMapMacro +BenchmarkQueryColumnMapMacro-4 17889 71254 ns/op 147552 B/op 4 allocs/op +BenchmarkQueryColumnMapReflect +BenchmarkQueryColumnMapReflect-4 9592 114374 ns/op 147608 B/op 6 allocs/op + +BenchmarkQueryColumnMapSliceHand +BenchmarkQueryColumnMapSliceHand-4 7903 154506 ns/op 145944 B/op 1002 allocs/op +BenchmarkQueryColumnMapSliceMacro +BenchmarkQueryColumnMapSliceMacro-4 6750 151835 ns/op 188649 B/op 12 allocs/op +BenchmarkQueryColumnMapSliceReflect +BenchmarkQueryColumnMapSliceReflect-4 3522 314086 ns/op 212818 B/op 1018 allocs/op + +BenchmarkQueryCombineHand +BenchmarkQueryCombineHand-4 37981 31381 ns/op 65536 B/op 1 allocs/op +BenchmarkQueryCombineMacro +BenchmarkQueryCombineMacro-4 29568 37010 ns/op 65584 B/op 3 allocs/op +BenchmarkQueryCombineReflect +BenchmarkQueryCombineReflect-4 1999 578415 ns/op 177657 B/op 3006 allocs/op + +BenchmarkQueryGroupHand +BenchmarkQueryGroupHand-4 4983 201296 ns/op 195098 B/op 1003 allocs/op +BenchmarkQueryGroupMacro +BenchmarkQueryGroupMacro-4 11942 104433 ns/op 155810 B/op 10 allocs/op +BenchmarkQueryGroupReflect +BenchmarkQueryGroupReflect-4 1810 643851 ns/op 275994 B/op 4017 allocs/op + +BenchmarkQueryJoinHand +BenchmarkQueryJoinHand-4 6081 180254 ns/op 256049 B/op 1031 allocs/op +BenchmarkQueryJoinMacro +BenchmarkQueryJoinMacro-4 7669 132689 ns/op 156995 B/op 17 allocs/op +BenchmarkQueryJoinReflect +BenchmarkQueryJoinReflect-4 1252 805528 ns/op 472557 B/op 4039 allocs/op + +BenchmarkQuerySelectHand +BenchmarkQuerySelectHand-4 360092 3073 ns/op 1024 B/op 1 allocs/op +BenchmarkQuerySelectMacro +BenchmarkQuerySelectMacro-4 204452 5238 ns/op 1048 B/op 2 allocs/op +BenchmarkQuerySelectReflect +BenchmarkQuerySelectReflect-4 3679 301481 ns/op 26096 B/op 2004 allocs/op + +BenchmarkQuerySortHand +BenchmarkQuerySortHand-4 2088 490302 ns/op 57480 B/op 4 allocs/op +BenchmarkQuerySortMacro +BenchmarkQuerySortMacro-4 3784 321839 ns/op 57488 B/op 7 allocs/op +BenchmarkQuerySortReflect +BenchmarkQuerySortReflect-4 1339 833588 ns/op 57848 B/op 20 allocs/op + +BenchmarkQueryWhereHand +BenchmarkQueryWhereHand-4 62037 17216 ns/op 57344 B/op 1 allocs/op +BenchmarkQueryWhereMacro +BenchmarkQueryWhereMacro-4 49932 20469 ns/op 57368 B/op 2 allocs/op +BenchmarkQueryWhereReflect +BenchmarkQueryWhereReflect-4 5196 233892 ns/op 25072 B/op 2003 allocs/op -BenchmarkQueryWhereHand-8 100000 18973 ns/op 57344 B/op 1 allocs/op -BenchmarkQueryWhereMacro-8 100000 19157 ns/op 57408 B/op 3 allocs/op -BenchmarkQueryWhereReflect-8 10000 207993 ns/op 48064 B/op 2002 allocs/op PASS -ok github.com/fishedee/tools/cmd/gen 43.099s +ok github.com/fishedee/tools/cmd/gen 38.660s ``` 我们从性能测试的结果可以看出,自动生成的代码至少和手工写的代码一样优化,在一些特定的场景下(group,join,sort),自动生成的代码由于高度优化的算法实现,和仔细的内存分配,它甚至比手工写的代码要快1倍。想知道为什么,可以看一下自动生成的[代码](https://github.com/fishedee/tools/blob/master/query/testdata/testdata_querygen.go) diff --git a/cmd/gen/Makefile b/cmd/gen/Makefile index 9a1bd1e..d2c7c6a 100644 --- a/cmd/gen/Makefile +++ b/cmd/gen/Makefile @@ -1,6 +1,7 @@ .PHONY:gen -bench:gen - go test . -bench=. -benchmem -v +bench_only: + go test . -bench=. -benchmem -v +bench:gen bench_only gen: go install github.com/fishedee/tools/cmd/gen rm -rf testdata/testdata_querygen.go diff --git a/cmd/gen/querycolumnmap.go b/cmd/gen/querycolumnmap.go index 17cf088..4c128df 100644 --- a/cmd/gen/querycolumnmap.go +++ b/cmd/gen/querycolumnmap.go @@ -52,8 +52,10 @@ func QueryColumnMapGen(request QueryGenRequest) *QueryGenResponse { }) } initBody := excuteTemplate(queryColumnMapInitTmpl, map[string]string{ - "signature": signature, - "argumentDefine": argumentDefine, + "signature": signature, + "firstArgElemType": getTypeDeclareCode(line, firstArgElem), + "firstArgElemColumnType": getTypeDeclareCode(line, columnArgType), + "argumentDefine": argumentDefine, }) return &QueryGenResponse{ importPackage: importPackage, @@ -90,7 +92,7 @@ func init() { panic(err) } queryColumnMapInitTmpl, err = template.New("name").Parse(` - query.ColumnMapMacroRegister({{.argumentDefine}},` + columnMapFuncPrefix + `{{.signature}}) + query.ColumnMapMacroRegister[{{ .firstArgElemType }}, {{ .firstArgElemColumnType }}]({{.argumentDefine}},` + columnMapFuncPrefix + `{{.signature}}) `) if err != nil { panic(err) diff --git a/cmd/gen/querycolumnmap_test.go b/cmd/gen/querycolumnmap_test.go index 5b93d79..d0a2c0f 100644 --- a/cmd/gen/querycolumnmap_test.go +++ b/cmd/gen/querycolumnmap_test.go @@ -16,12 +16,12 @@ func TestQueryColumnMap(t *testing.T) { {UserID: -2}, {UserID: 3}, } - assert.Equal(t, query.ColumnMap[gentestdata.User, int](data, "UserID"), map[int]gentestdata.User{ + assert.Equal(t, query.ColumnMap[gentestdata.User, int, map[int]gentestdata.User](data, "UserID"), map[int]gentestdata.User{ 1: {UserID: 1}, -2: {UserID: -2}, 3: {UserID: 3}, }) - assert.Equal(t, query.ColumnMap[int, int]([]int{5, 6, 8, 8, 0, 6}, "."), map[int]int{ + assert.Equal(t, query.ColumnMap[int, int, map[int]int]([]int{5, 6, 8, 8, 0, 6}, "."), map[int]int{ 5: 5, 6: 6, 8: 8, @@ -64,7 +64,7 @@ func BenchmarkQueryColumnMapMacro(b *testing.B) { b.ResetTimer() for i := 0; i != b.N; i++ { - query.ColumnMap[gentestdata.User, int](data, "UserID") + query.ColumnMap[gentestdata.User, int, map[int]gentestdata.User](data, "UserID") } } @@ -73,7 +73,7 @@ func BenchmarkQueryColumnMapReflect(b *testing.B) { b.ResetTimer() for i := 0; i != b.N; i++ { - query.ColumnMap[gentestdata.User, int](data, "Age") + query.ColumnMap[gentestdata.User, int, map[int]gentestdata.User](data, "Age") } } @@ -96,7 +96,7 @@ func BenchmarkQueryColumnMapSliceMacro(b *testing.B) { b.ResetTimer() for i := 0; i != b.N; i++ { - query.ColumnMap[gentestdata.User, int](data, "[]UserID") + query.ColumnMap[gentestdata.User, int, map[int][]gentestdata.User](data, "[]UserID") } } @@ -105,6 +105,6 @@ func BenchmarkQueryColumnMapSliceReflect(b *testing.B) { b.ResetTimer() for i := 0; i != b.N; i++ { - query.ColumnMap[gentestdata.User, int](data, "[]Age") + query.ColumnMap[gentestdata.User, int, map[int][]gentestdata.User](data, "[]Age") } } diff --git a/cmd/gen/querygroup.go b/cmd/gen/querygroup.go index de2e327..b022399 100644 --- a/cmd/gen/querygroup.go +++ b/cmd/gen/querygroup.go @@ -140,7 +140,7 @@ func init() { {{end}} } - return {{if eq .isSliceReturn ""}} {{else}}&{{end}}result + return {{if eq .isFunctorGroup "true"}}{{if eq .isSliceReturn ""}} {{else}}&{{end}}{{end}}result } `) if err != nil { diff --git a/cmd/gen/testdata/data.go b/cmd/gen/testdata/data.go index 204d509..0d23d43 100644 --- a/cmd/gen/testdata/data.go +++ b/cmd/gen/testdata/data.go @@ -79,19 +79,19 @@ func logic() { query.Sort([]User{}, "UserID asc") query.Sort([]int{}, ". desc") query.Sort([]Admin{}, "IsMale asc") - query.ColumnMap[User, int]([]User{}, "UserID") - query.ColumnMap[User, string]([]User{}, "Name") - query.ColumnMap[User, int]([]User{}, "[]UserID") - query.ColumnMap[int, int]([]int{}, ".") - query.ColumnMap[int, int]([]int{}, " . ") - query.ColumnMap[string, string]([]string{}, " . ") - query.ColumnMap[ContentType, string]([]ContentType{}, " Name ") - query.ColumnMap[ContentType, string]([]ContentType{}, " Name ") - query.ColumnMap[ContentType, int]([]ContentType{}, "Age ") - query.ColumnMap[ContentType, bool]([]ContentType{}, "Ok ") - query.ColumnMap[ContentType, float32]([]ContentType{}, " Money ") - query.ColumnMap[ContentType, float64]([]ContentType{}, " CardMoney") - query.ColumnMap[QueryInnerStruct2, int]([]QueryInnerStruct2{}, "QueryInnerStruct.MM") + query.ColumnMap[User, int, map[int]User]([]User{}, "UserID") + query.ColumnMap[User, string, map[string]User]([]User{}, "Name") + query.ColumnMap[User, int, map[int][]User]([]User{}, "[]UserID") + query.ColumnMap[int, int, map[int]int]([]int{}, ".") + query.ColumnMap[int, int, map[int]int]([]int{}, " . ") + query.ColumnMap[string, string, map[string]string]([]string{}, " . ") + query.ColumnMap[ContentType, string, map[string]ContentType]([]ContentType{}, " Name ") + query.ColumnMap[ContentType, string, map[string]ContentType]([]ContentType{}, " Name ") + query.ColumnMap[ContentType, int, map[int]ContentType]([]ContentType{}, "Age ") + query.ColumnMap[ContentType, bool, map[bool]ContentType]([]ContentType{}, "Ok ") + query.ColumnMap[ContentType, float32, map[float32]ContentType]([]ContentType{}, " Money ") + query.ColumnMap[ContentType, float64, map[float64]ContentType]([]ContentType{}, " CardMoney") + query.ColumnMap[QueryInnerStruct2, int, map[int]QueryInnerStruct2]([]QueryInnerStruct2{}, "QueryInnerStruct.MM") query.Group[User, Department, []Department]([]User{}, "UserID", func(user []User) Department { return Department{} }) @@ -125,33 +125,33 @@ func logic() { "Name", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, float32](list, " Money ")) - list[0].Money = sum.(float32) + list[0].Money = sum return []ContentType{list[0]} }) query.Group[ContentType, float32, []float32]([]ContentType{}, "Name", func(list []ContentType) float32 { - sum := query.Sum(query.Column[ContentType, float32](list, " Money ")).(float32) + sum := query.Sum(query.Column[ContentType, float32](list, " Money ")) return sum }) query.Group[ContentType, []ContentType, *[]ContentType]([]ContentType{}, "Ok", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, float64](list, "CardMoney ")) - list[0].CardMoney = sum.(float64) + list[0].CardMoney = sum return []ContentType{list[0]} }) query.Group[ContentType, []ContentType, *[]ContentType]([]ContentType{}, " Age ", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")) - list[0].CardMoney = sum.(float64) + list[0].CardMoney = sum return []ContentType{list[0]} }) query.Group[ContentType, float64, []float64]([]ContentType{}, " Age ", func(list []ContentType) float64 { - sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")).(float64) + sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")) return sum }) @@ -159,27 +159,27 @@ func logic() { " Age ", func(list []ContentType) []float64 { sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")) - return []float64{sum.(float64)} + return []float64{sum} }) query.Group[ContentType, int, []int]([]ContentType{}, "Register ", func(list []ContentType) int { sum := query.Sum(query.Column[ContentType, int](list, " Age ")) - return sum.(int) + return sum }) query.Group[ContentType, []ContentType, *[]ContentType]([]ContentType{}, "Register ", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, int](list, " Age ")) - list[0].Age = sum.(int) + list[0].Age = sum return []ContentType{list[0]} }) query.Group[QueryInnerStruct2, []QueryInnerStruct2, *[]QueryInnerStruct2]([]QueryInnerStruct2{}, "QueryInnerStruct.MM", func(list []QueryInnerStruct2) []QueryInnerStruct2 { sum := query.Sum(query.Column[QueryInnerStruct2, int](list, " MM ")) - list[0].MM = sum.(int) + list[0].MM = sum return []QueryInnerStruct2{list[0]} }) query.LeftJoin([]Admin{}, []User{}, "AdminID = UserID", func(left Admin, right User) AdminUser { diff --git a/cmd/gen/testdata/testdata_querygen.go b/cmd/gen/testdata/testdata_querygen.go index 5ce2759..3e341af 100644 --- a/cmd/gen/testdata/testdata_querygen.go +++ b/cmd/gen/testdata/testdata_querygen.go @@ -1,10 +1,364 @@ package testdata import ( + "github.com/fishedee/tools/cmd/gen/testdata/subtest" "github.com/fishedee/tools/query" - testdata "github.com/fishedee/tools/query/test_data" + "github.com/fishedee/tools/query/test_data" + "time" ) +func queryColumnMapV1634476ac5d81ffe821151e2cd007944bb75387e(data []testdata.ContentType, column string) map[string]testdata.ContentType { + dataIn := data + result := make(map[string]testdata.ContentType, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].Name] = dataIn[i] + } + return result +} + +func queryColumnMapV28f674724a19ea93b16beb429196eaa567b10f28(data []User, column string) map[int][]User { + dataIn := data + bufferData := make([]User, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + result := make(map[int][]User, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].UserID + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].UserID] = bufferData[kbegin:k] + + } + + return result +} + +func queryColumnMapV3923b792e276005e09637544ecb3aec8be870f41(data []string, column string) map[string]string { + dataIn := data + result := make(map[string]string, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i]] = dataIn[i] + } + return result +} + +func queryColumnMapV3c9c70c40c63019848d44a57a05b107340215e80(data []testdata.ContentType, column string) map[float32]testdata.ContentType { + dataIn := data + result := make(map[float32]testdata.ContentType, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].Money] = dataIn[i] + } + return result +} + +func queryColumnMapV3f666f2858a8335d8dedbc686b034302e2f4fc0f(data []testdata.ContentType, column string) map[float64]testdata.ContentType { + dataIn := data + result := make(map[float64]testdata.ContentType, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].CardMoney] = dataIn[i] + } + return result +} + +func queryColumnMapV74382f13397675a69df627f3964ab4362f62b343(data []User, column string) map[string]User { + dataIn := data + result := make(map[string]User, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].Name] = dataIn[i] + } + return result +} + +func queryColumnMapV84f666378aff13a68045428e41ef52e9bf17a800(data []testdata.QueryInnerStruct2, column string) map[int]testdata.QueryInnerStruct2 { + dataIn := data + result := make(map[int]testdata.QueryInnerStruct2, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].QueryInnerStruct.MM] = dataIn[i] + } + return result +} + +func queryColumnMapV890fbb2d61811a21c543c5d899f2e91b964343eb(data []testdata.ContentType, column string) map[bool]testdata.ContentType { + dataIn := data + result := make(map[bool]testdata.ContentType, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].Ok] = dataIn[i] + } + return result +} + +func queryColumnMapV8be389735876e433a498564bd3f63c8f1232d915(data []testdata.ContentType, column string) map[string]testdata.ContentType { + dataIn := data + result := make(map[string]testdata.ContentType, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].Name] = dataIn[i] + } + return result +} + +func queryColumnMapV904b262f8e2329ec73c320ca0e5ca82f14165586(data []int, column string) map[int]int { + dataIn := data + result := make(map[int]int, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i]] = dataIn[i] + } + return result +} + +func queryColumnMapV91dacd60e87431951940b4b4c51428e7c1e5c1f2(data []int, column string) map[int]int { + dataIn := data + result := make(map[int]int, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i]] = dataIn[i] + } + return result +} + +func queryColumnMapV9379e410e09e784ed64aa5e8311734b853ca1260(data []testdata.ContentType, column string) map[int]testdata.ContentType { + dataIn := data + result := make(map[int]testdata.ContentType, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].Age] = dataIn[i] + } + return result +} + +func queryColumnMapVac46a6e2d4d6d4f163cc177eb335bc2bb166d92b(data []User, column string) map[int]User { + dataIn := data + result := make(map[int]User, len(dataIn)) + + for i := len(dataIn) - 1; i >= 0; i-- { + result[dataIn[i].UserID] = dataIn[i] + } + return result +} + +func queryColumnV1326c8079077532a2df04e5705513b21ec7ccfde(data []testdata.ContentType, column string) []float64 { + dataIn := data + result := make([]float64, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.CardMoney + } + return result +} + +func queryColumnV1634476ac5d81ffe821151e2cd007944bb75387e(data []testdata.ContentType, column string) []string { + dataIn := data + result := make([]string, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Name + } + return result +} + +func queryColumnV3923b792e276005e09637544ecb3aec8be870f41(data []string, column string) []string { + dataIn := data + result := make([]string, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single + } + return result +} + +func queryColumnV3c9c70c40c63019848d44a57a05b107340215e80(data []testdata.ContentType, column string) []float32 { + dataIn := data + result := make([]float32, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Money + } + return result +} + +func queryColumnV3f666f2858a8335d8dedbc686b034302e2f4fc0f(data []testdata.ContentType, column string) []float64 { + dataIn := data + result := make([]float64, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.CardMoney + } + return result +} + +func queryColumnV67d1dbaa7a84019e2b2b100fc5d35aa18ad7d0ce(data []testdata.ContentType, column string) []float64 { + dataIn := data + result := make([]float64, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.CardMoney + } + return result +} + +func queryColumnV74382f13397675a69df627f3964ab4362f62b343(data []User, column string) []string { + dataIn := data + result := make([]string, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Name + } + return result +} + +func queryColumnV84f666378aff13a68045428e41ef52e9bf17a800(data []testdata.QueryInnerStruct2, column string) []int { + dataIn := data + result := make([]int, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.QueryInnerStruct.MM + } + return result +} + +func queryColumnV890fbb2d61811a21c543c5d899f2e91b964343eb(data []testdata.ContentType, column string) []bool { + dataIn := data + result := make([]bool, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Ok + } + return result +} + +func queryColumnV8be389735876e433a498564bd3f63c8f1232d915(data []testdata.ContentType, column string) []string { + dataIn := data + result := make([]string, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Name + } + return result +} + +func queryColumnV904b262f8e2329ec73c320ca0e5ca82f14165586(data []int, column string) []int { + dataIn := data + result := make([]int, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single + } + return result +} + +func queryColumnV91dacd60e87431951940b4b4c51428e7c1e5c1f2(data []int, column string) []int { + dataIn := data + result := make([]int, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single + } + return result +} + +func queryColumnV9379e410e09e784ed64aa5e8311734b853ca1260(data []testdata.ContentType, column string) []int { + dataIn := data + result := make([]int, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Age + } + return result +} + +func queryColumnVac46a6e2d4d6d4f163cc177eb335bc2bb166d92b(data []User, column string) []int { + dataIn := data + result := make([]int, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.UserID + } + return result +} + +func queryColumnVb6a4a6f17a7bc9f4857b953563c0a001e04b0df4(data []subtest.Address, column string) []string { + dataIn := data + result := make([]string, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.City + } + return result +} + +func queryColumnVba800328deafbc2a4fbda5fd19e9eaca7bd4f9a1(data []testdata.ContentType, column string) []float32 { + dataIn := data + result := make([]float32, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Money + } + return result +} + +func queryColumnVc2be6eac9135e9e0a63d2c9155bea08a4f3c2b5e(data []testdata.QueryInnerStruct2, column string) []int { + dataIn := data + result := make([]int, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.MM + } + return result +} + +func queryColumnVc6bebe695f9ff26a9409d88809a85fd9cceda86d(data []User, column string) []User { + dataIn := data + result := make([]User, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single + } + return result +} + +func queryColumnVd8a8ba7093b7cf4407a40f064340077d6ad3be2f(data []testdata.ContentType, column string) []int { + dataIn := data + result := make([]int, len(dataIn), len(dataIn)) + + for i, single := range dataIn { + result[i] = single.Age + } + return result +} + func queryCombineV32ceb64b78fbf30e491600c88b60e25966b3d0c0(leftData []testdata.ContentType, rightData []int, combineFunctor func(testdata.ContentType, int) testdata.ContentType) []testdata.ContentType { leftDataIn := leftData rightDataIn := rightData @@ -53,6 +407,710 @@ func queryCombineVdd9cf383efe9adb9dedf293cf43f875133066c23(leftData []Admin, rig return newData } +func queryGroupV289d77ccfff4ea272a58267e3b9c9de43411f84b(data []string, groupType string, groupFunctor func([]string) testdata.ContentType) []testdata.ContentType { + dataIn := data + bufferData := make([]string, len(dataIn), len(dataIn)) + mapData := make(map[string]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]testdata.ContentType, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i] + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + +func queryGroupV5e87b2e0994d2f6b51e103cd03f0e20bc2b60c2a(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) int) []int { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[time.Time]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]int, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Register + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + +func queryGroupV7959aac2ba701c92b02938af82c21599cbf58c3d(data []int, groupType string, groupFunctor func([]int) int) []int { + dataIn := data + bufferData := make([]int, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]int, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i] + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + +func queryGroupV7c15a02754e8e39a158cd3d3e8088258012c6f55(data []User, groupType string, groupFunctor func([]User) Department) []Department { + dataIn := data + bufferData := make([]User, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]Department, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].UserID + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + +func queryGroupV80b407696d3665d0652382da3e9fda32506f530f(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) []float64) *[]float64 { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]float64, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Age + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVb0f32b70a6b484b0da2fb2a791874fe6a632fbf5(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) []testdata.ContentType) *[]testdata.ContentType { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]testdata.ContentType, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Age + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVb6f1c2171838a5cc1ac9e63d0ecaada8ee2f1e41(data []User, groupType string, groupFunctor func([]User) Department) []Department { + dataIn := data + bufferData := make([]User, len(dataIn), len(dataIn)) + mapData := make(map[time.Time]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]Department, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].CreateTime + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + +func queryGroupVb7a74b6b9fc71210fab248a70af4f4beccf9c794(data []testdata.QueryInnerStruct2, groupType string, groupFunctor func([]testdata.QueryInnerStruct2) []testdata.QueryInnerStruct2) *[]testdata.QueryInnerStruct2 { + dataIn := data + bufferData := make([]testdata.QueryInnerStruct2, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]testdata.QueryInnerStruct2, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].QueryInnerStruct.MM + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVd527b6188165d052cd11b364e72e6bdfe4fd76d6(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) []testdata.ContentType) *[]testdata.ContentType { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[string]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]testdata.ContentType, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Name + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVd9d416d8cc0214bf9f6454fc0f9361ce6d224172(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) []testdata.ContentType) *[]testdata.ContentType { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[bool]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]testdata.ContentType, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Ok + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVe43c990928ddf5d988a6464ebd9aa14669069506(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) []testdata.ContentType) *[]testdata.ContentType { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[bool]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]testdata.ContentType, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Ok + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVe7d5282fd7785eff7f4ab513493be85a01ef834b(data []User, groupType string, groupFunctor func([]User) []Department) *[]Department { + dataIn := data + bufferData := make([]User, len(dataIn), len(dataIn)) + mapData := make(map[time.Time]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]Department, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].CreateTime + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVec4d3b2c280c9fc398a0f8a554bc1c2ec7010257(data []int, groupType string, groupFunctor func([]int) Department) []Department { + dataIn := data + bufferData := make([]int, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]Department, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i] + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + +func queryGroupVed5e4b40611c7106ad6cc07c33aef9aa052ff6f1(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) float64) []float64 { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]float64, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Age + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + +func queryGroupVef320495b62cbaeae4ebd6f3805c6b2d56041b01(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) []testdata.ContentType) *[]testdata.ContentType { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[time.Time]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]testdata.ContentType, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Register + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single...) + + } + + return &result +} + +func queryGroupVf7bec03379fe55d2997b3d5ac7360bbc400c27f3(data []testdata.ContentType, groupType string, groupFunctor func([]testdata.ContentType) float32) []float32 { + dataIn := data + bufferData := make([]testdata.ContentType, len(dataIn), len(dataIn)) + mapData := make(map[string]int, len(dataIn)) + groupFunctorIn := groupFunctor + result := make([]float32, 0, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Name + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + single := groupFunctorIn(bufferData[kbegin:k]) + result = append(result, single) + + } + + return result +} + func queryJoinV29a4e5efaa3321b67511a20dc57f29e0ec5aa0cf(leftData []Admin, rightData []User, joinPlace, joinType string, joinFunctor func(Admin, User) AdminUser) []AdminUser { leftDataIn := leftData rightDataIn := rightData @@ -242,6 +1300,15 @@ func queryJoinV4f860e3bcc925b8d2d6fae8fab6a2a5cc4fba96f(leftData []Admin, rightD return result } +func querySelectV6ee296b569bde42f94e969ef503e43ca5827eda6(data []int, selectFunctor func(a int) User) []User { + result := make([]User, len(data), len(data)) + + for i, single := range data { + result[i] = selectFunctor(single) + } + return result +} + func querySelectVd595e8831f2025c62e11d6273f64a4d65d32f4c2(data []User, selectFunctor func(a User) Sex) []Sex { result := make([]Sex, len(data), len(data)) @@ -361,6 +1428,70 @@ func queryWhereVdf6742e675632943121cefdb3ad29ba75c08eaac(data []int, whereFuncto func init() { + query.ColumnMapMacroRegister[testdata.ContentType, string]([]testdata.ContentType{}, " Name ", queryColumnMapV1634476ac5d81ffe821151e2cd007944bb75387e) + + query.ColumnMapMacroRegister[User, int]([]User{}, "[]UserID", queryColumnMapV28f674724a19ea93b16beb429196eaa567b10f28) + + query.ColumnMapMacroRegister[string, string]([]string{}, " . ", queryColumnMapV3923b792e276005e09637544ecb3aec8be870f41) + + query.ColumnMapMacroRegister[testdata.ContentType, float32]([]testdata.ContentType{}, " Money ", queryColumnMapV3c9c70c40c63019848d44a57a05b107340215e80) + + query.ColumnMapMacroRegister[testdata.ContentType, float64]([]testdata.ContentType{}, " CardMoney", queryColumnMapV3f666f2858a8335d8dedbc686b034302e2f4fc0f) + + query.ColumnMapMacroRegister[User, string]([]User{}, "Name", queryColumnMapV74382f13397675a69df627f3964ab4362f62b343) + + query.ColumnMapMacroRegister[testdata.QueryInnerStruct2, int]([]testdata.QueryInnerStruct2{}, "QueryInnerStruct.MM", queryColumnMapV84f666378aff13a68045428e41ef52e9bf17a800) + + query.ColumnMapMacroRegister[testdata.ContentType, bool]([]testdata.ContentType{}, "Ok ", queryColumnMapV890fbb2d61811a21c543c5d899f2e91b964343eb) + + query.ColumnMapMacroRegister[testdata.ContentType, string]([]testdata.ContentType{}, " Name ", queryColumnMapV8be389735876e433a498564bd3f63c8f1232d915) + + query.ColumnMapMacroRegister[int, int]([]int{}, ".", queryColumnMapV904b262f8e2329ec73c320ca0e5ca82f14165586) + + query.ColumnMapMacroRegister[int, int]([]int{}, " . ", queryColumnMapV91dacd60e87431951940b4b4c51428e7c1e5c1f2) + + query.ColumnMapMacroRegister[testdata.ContentType, int]([]testdata.ContentType{}, "Age ", queryColumnMapV9379e410e09e784ed64aa5e8311734b853ca1260) + + query.ColumnMapMacroRegister[User, int]([]User{}, "UserID", queryColumnMapVac46a6e2d4d6d4f163cc177eb335bc2bb166d92b) + + query.ColumnMacroRegister([]testdata.ContentType{}, "CardMoney ", queryColumnV1326c8079077532a2df04e5705513b21ec7ccfde) + + query.ColumnMacroRegister([]testdata.ContentType{}, " Name ", queryColumnV1634476ac5d81ffe821151e2cd007944bb75387e) + + query.ColumnMacroRegister([]string{}, " . ", queryColumnV3923b792e276005e09637544ecb3aec8be870f41) + + query.ColumnMacroRegister([]testdata.ContentType{}, " Money ", queryColumnV3c9c70c40c63019848d44a57a05b107340215e80) + + query.ColumnMacroRegister([]testdata.ContentType{}, " CardMoney", queryColumnV3f666f2858a8335d8dedbc686b034302e2f4fc0f) + + query.ColumnMacroRegister([]testdata.ContentType{}, " CardMoney ", queryColumnV67d1dbaa7a84019e2b2b100fc5d35aa18ad7d0ce) + + query.ColumnMacroRegister([]User{}, "Name", queryColumnV74382f13397675a69df627f3964ab4362f62b343) + + query.ColumnMacroRegister([]testdata.QueryInnerStruct2{}, "QueryInnerStruct.MM", queryColumnV84f666378aff13a68045428e41ef52e9bf17a800) + + query.ColumnMacroRegister([]testdata.ContentType{}, "Ok ", queryColumnV890fbb2d61811a21c543c5d899f2e91b964343eb) + + query.ColumnMacroRegister([]testdata.ContentType{}, " Name ", queryColumnV8be389735876e433a498564bd3f63c8f1232d915) + + query.ColumnMacroRegister([]int{}, ".", queryColumnV904b262f8e2329ec73c320ca0e5ca82f14165586) + + query.ColumnMacroRegister([]int{}, " . ", queryColumnV91dacd60e87431951940b4b4c51428e7c1e5c1f2) + + query.ColumnMacroRegister([]testdata.ContentType{}, "Age ", queryColumnV9379e410e09e784ed64aa5e8311734b853ca1260) + + query.ColumnMacroRegister([]User{}, "UserID", queryColumnVac46a6e2d4d6d4f163cc177eb335bc2bb166d92b) + + query.ColumnMacroRegister([]subtest.Address{}, "City", queryColumnVb6a4a6f17a7bc9f4857b953563c0a001e04b0df4) + + query.ColumnMacroRegister([]testdata.ContentType{}, " Money ", queryColumnVba800328deafbc2a4fbda5fd19e9eaca7bd4f9a1) + + query.ColumnMacroRegister([]testdata.QueryInnerStruct2{}, " MM ", queryColumnVc2be6eac9135e9e0a63d2c9155bea08a4f3c2b5e) + + query.ColumnMacroRegister([]User{}, ".", queryColumnVc6bebe695f9ff26a9409d88809a85fd9cceda86d) + + query.ColumnMacroRegister([]testdata.ContentType{}, " Age ", queryColumnVd8a8ba7093b7cf4407a40f064340077d6ad3be2f) + query.CombineMacroRegister([]testdata.ContentType{}, []int{}, (func(testdata.ContentType, int) testdata.ContentType)(nil), queryCombineV32ceb64b78fbf30e491600c88b60e25966b3d0c0) query.CombineMacroRegister([]int{}, []User{}, (func(int, User) User)(nil), queryCombineV38f41d1ea9151d195cb01ed01c28e94b7fbd938b) @@ -369,12 +1500,46 @@ func init() { query.CombineMacroRegister([]Admin{}, []User{}, (func(Admin, User) AdminUser)(nil), queryCombineVdd9cf383efe9adb9dedf293cf43f875133066c23) + query.GroupMacroRegister([]string{}, ".", (func([]string) testdata.ContentType)(nil), queryGroupV289d77ccfff4ea272a58267e3b9c9de43411f84b) + + query.GroupMacroRegister([]testdata.ContentType{}, "Register ", (func([]testdata.ContentType) int)(nil), queryGroupV5e87b2e0994d2f6b51e103cd03f0e20bc2b60c2a) + + query.GroupMacroRegister([]int{}, ".", (func([]int) int)(nil), queryGroupV7959aac2ba701c92b02938af82c21599cbf58c3d) + + query.GroupMacroRegister([]User{}, "UserID", (func([]User) Department)(nil), queryGroupV7c15a02754e8e39a158cd3d3e8088258012c6f55) + + query.GroupMacroRegister([]testdata.ContentType{}, " Age ", (func([]testdata.ContentType) []float64)(nil), queryGroupV80b407696d3665d0652382da3e9fda32506f530f) + + query.GroupMacroRegister([]testdata.ContentType{}, " Age ", (func([]testdata.ContentType) []testdata.ContentType)(nil), queryGroupVb0f32b70a6b484b0da2fb2a791874fe6a632fbf5) + + query.GroupMacroRegister([]User{}, "CreateTime", (func([]User) Department)(nil), queryGroupVb6f1c2171838a5cc1ac9e63d0ecaada8ee2f1e41) + + query.GroupMacroRegister([]testdata.QueryInnerStruct2{}, "QueryInnerStruct.MM", (func([]testdata.QueryInnerStruct2) []testdata.QueryInnerStruct2)(nil), queryGroupVb7a74b6b9fc71210fab248a70af4f4beccf9c794) + + query.GroupMacroRegister([]testdata.ContentType{}, "Name", (func([]testdata.ContentType) []testdata.ContentType)(nil), queryGroupVd527b6188165d052cd11b364e72e6bdfe4fd76d6) + + query.GroupMacroRegister([]testdata.ContentType{}, "Ok", (func([]testdata.ContentType) []testdata.ContentType)(nil), queryGroupVd9d416d8cc0214bf9f6454fc0f9361ce6d224172) + + query.GroupMacroRegister([]testdata.ContentType{}, " Ok ", (func([]testdata.ContentType) []testdata.ContentType)(nil), queryGroupVe43c990928ddf5d988a6464ebd9aa14669069506) + + query.GroupMacroRegister([]User{}, "CreateTime", (func([]User) []Department)(nil), queryGroupVe7d5282fd7785eff7f4ab513493be85a01ef834b) + + query.GroupMacroRegister([]int{}, ".", (func([]int) Department)(nil), queryGroupVec4d3b2c280c9fc398a0f8a554bc1c2ec7010257) + + query.GroupMacroRegister([]testdata.ContentType{}, " Age ", (func([]testdata.ContentType) float64)(nil), queryGroupVed5e4b40611c7106ad6cc07c33aef9aa052ff6f1) + + query.GroupMacroRegister([]testdata.ContentType{}, "Register ", (func([]testdata.ContentType) []testdata.ContentType)(nil), queryGroupVef320495b62cbaeae4ebd6f3805c6b2d56041b01) + + query.GroupMacroRegister([]testdata.ContentType{}, "Name", (func([]testdata.ContentType) float32)(nil), queryGroupVf7bec03379fe55d2997b3d5ac7360bbc400c27f3) + query.JoinMacroRegister([]Admin{}, []User{}, "left", "AdminID = UserID", (func(Admin, User) AdminUser)(nil), queryJoinV29a4e5efaa3321b67511a20dc57f29e0ec5aa0cf) query.JoinMacroRegister([]User{}, []int{}, "right", "UserID = .", (func(User, int) User)(nil), queryJoinV3b9eb26d0b915e0c6d26c912e94883240a196b12) query.JoinMacroRegister([]Admin{}, []User{}, "inner", "AdminID = UserID", (func(Admin, User) AdminUser)(nil), queryJoinV4f860e3bcc925b8d2d6fae8fab6a2a5cc4fba96f) + query.SelectMacroRegister([]int{}, (func(int) User)(nil), querySelectV6ee296b569bde42f94e969ef503e43ca5827eda6) + query.SelectMacroRegister([]User{}, (func(User) Sex)(nil), querySelectVd595e8831f2025c62e11d6273f64a4d65d32f4c2) query.SortMacroRegister([]User{}, "UserID asc", querySortV24a673fdaa750030447c9f4189cf7c07434d6efc) diff --git a/query/internal/query/query.go b/query/internal/query/query.go index 373f360..e24ff7d 100644 --- a/query/internal/query/query.go +++ b/query/internal/query/query.go @@ -482,18 +482,17 @@ func ColumnReflect[T, R any](data []T, column string) []R { } // ColumnMapReflect 反射 -func ColumnMapReflect[T any, K comparable](data []T, column string) map[K]T { +func ColumnMapReflect[T any, K comparable, R map[K]T | map[K][]T](data []T, column string) R { column = strings.Trim(column, " ") - // 返回值类型不一致,暂时去掉 - // if len(column) >= 2 && column[0:2] == "[]" { - // column = column[2:] - // return columnMapReflectSlice[T, K](data, column) - // } else { - return columnMapReflectSingle[T, K](data, column) - // } + if len(column) >= 2 && column[0:2] == "[]" { + column = column[2:] + return columnMapReflectSlice(data, column).(R) + } else { + return columnMapReflectSingle(data, column).(R) + } } -func columnMapReflectSlice[T any, K comparable](data []T, column string) map[K][]T { +func columnMapReflectSlice(data interface{}, column string) interface{} { dataValue := reflect.ValueOf(data) dataValueType := dataValue.Type() dataType := dataValue.Type().Elem() @@ -507,10 +506,10 @@ func columnMapReflectSlice[T any, K comparable](data []T, column string) map[K][ singleResultValue := dataFieldExtract(group.Index(0)) resultValue.SetMapIndex(singleResultValue, group) }) - return resultValue.Interface().(map[K][]T) + return resultValue.Interface() } -func columnMapReflectSingle[T any, K comparable](data []T, column string) map[K]T { +func columnMapReflectSingle(data interface{}, column string) interface{} { dataValue := reflect.ValueOf(data) dataType := dataValue.Type().Elem() dataLen := dataValue.Len() @@ -523,7 +522,7 @@ func columnMapReflectSingle[T any, K comparable](data []T, column string) map[K] singleResultValue := dataFieldExtract(singleDataValue) resultValue.SetMapIndex(singleResultValue, singleDataValue) } - return resultValue.Interface().(map[K]T) + return resultValue.Interface() } // CombineReflect 反射 diff --git a/query/query.go b/query/query.go index 1e0a06f..4a5587d 100644 --- a/query/query.go +++ b/query/query.go @@ -1,8 +1,8 @@ package query import ( + "fmt" "log" - "math" "reflect" "runtime" "sort" @@ -209,10 +209,10 @@ func Column[T, R any](data []T, column string) []R { } // ColumnMapMacroHandler 扩展类函数 QueryColumnMap -type ColumnMapMacroHandler[T any, K comparable] func(data []T, column string) map[K]T +type ColumnMapMacroHandler[T any, K comparable, R map[K]T | map[K][]T] func(data []T, column string) R // ColumnMapMacroRegister 注册 -func ColumnMapMacroRegister[T any, K comparable](data []T, column string, handler ColumnMapMacroHandler[T, K]) { +func ColumnMapMacroRegister[T any, K comparable, R map[K]T | map[K][]T](data []T, column string, handler ColumnMapMacroHandler[T, K, R]) { id := registerQueryTypeID([]string{reflect.TypeOf(data).String(), column}) columnMapMacroMapper[id] = handler } @@ -222,15 +222,15 @@ func ColumnMapMacroRegister[T any, K comparable](data []T, column string, handle // * Second Argument:column name // result = query.ColumnMap(users, "UserID") // userMap := result.(map[int]User) -func ColumnMap[T any, K comparable](data []T, column string) map[K]T { +func ColumnMap[T any, K comparable, R map[K]T | map[K][]T](data []T, column string) R { id := getQueryTypeID([]string{reflect.TypeOf(data).String(), column}) handler, isExist := columnMapMacroMapper[id] if isExist { - return handler.(ColumnMapMacroHandler[T, K])(data, column) + return handler.(ColumnMapMacroHandler[T, K, R])(data, column) } reflectWarn("QueryColumnMap") - return query.ColumnMapReflect[T, K](data, column) + return query.ColumnMapReflect[T, K, R](data, column) } // LeftJoin join data from two table,support LeftJoin,RightJoin,InnerJoin和OuterJoin @@ -303,105 +303,52 @@ func Combine[L, R, LR any](leftData []L, rightData []R, combineFuctor func(L, R) // query.Reduce([]User{}, func(sum int, singleData User) int { // return 1 // }, 0) -func Reduce(data interface{}, reduceFuctor interface{}, resultReduce interface{}) interface{} { - dataValue := reflect.ValueOf(data) - dataLen := dataValue.Len() - - reduceFuctorValue := reflect.ValueOf(reduceFuctor) - resultReduceType := reduceFuctorValue.Type().In(0) - resultReduceValue := reflect.New(resultReduceType) - err := MapToArray(resultReduce, resultReduceValue.Interface(), "json") - if err != nil { - panic(err) +func Reduce[T, R any](data []T, reduceFuctor func(R, T) R, resultReduce R) R { + datalen := len(data) + for i := 0; i != datalen; i++ { + resultReduce = reduceFuctor(resultReduce, data[i]) } - resultReduceValue = resultReduceValue.Elem() + return resultReduce +} - for i := 0; i != dataLen; i++ { - singleDataValue := dataValue.Index(i) - resultReduceValue = reduceFuctorValue.Call([]reflect.Value{resultReduceValue, singleDataValue})[0] - } - return resultReduceValue.Interface() +type Number interface { + ~int | ~float32 | ~float64 } // Sum get the sum of data. // only support int, float32, float64 type -func Sum(data interface{}) interface{} { - dataType := reflect.TypeOf(data).Elem() - if dataType.Kind() == reflect.Int { - return Reduce(data, func(sum int, single int) int { - return sum + single - }, 0) - } else if dataType.Kind() == reflect.Float32 { - return Reduce(data, func(sum float32, single float32) float32 { - return sum + single - }, (float32)(0.0)) - } else if dataType.Kind() == reflect.Float64 { - return Reduce(data, func(sum float64, single float64) float64 { - return sum + single - }, 0.0) - } else { - panic("invalid type " + dataType.String()) - } +func Sum[T Number](data []T) T { + return Reduce(data, func(sum T, single T) T { + return sum + single + }, 0) } // Max get max value from table. // only support int, float32, float64 type -func Max(data interface{}) interface{} { - dataType := reflect.TypeOf(data).Elem() - if dataType.Kind() == reflect.Int { - return Reduce(data, func(max int, single int) int { - if single > max { - return single - } - return max - }, math.MinInt32) - } else if dataType.Kind() == reflect.Float32 { - return Reduce(data, func(max float32, single float32) float32 { - if single > max { - return single - } - return max - }, math.SmallestNonzeroFloat32) - } else if dataType.Kind() == reflect.Float64 { - return Reduce(data, func(max float64, single float64) float64 { - if single > max { - return single - } - return max - }, math.SmallestNonzeroFloat64) - } else { - panic("invalid type " + dataType.String()) +func Max[T Number](data []T) T { + if len(data) == 0 { + panic(fmt.Errorf("data length is 0")) } + return Reduce(data, func(r T, t T) T { + if t > r { + return t + } + return r + }, data[0]) } // Min get min value from table. // only support int, float32, float64 type -func Min(data interface{}) interface{} { - dataType := reflect.TypeOf(data).Elem() - if dataType.Kind() == reflect.Int { - return Reduce(data, func(min int, single int) int { - if single < min { - return single - } - return min - }, math.MaxInt32) - } else if dataType.Kind() == reflect.Float32 { - return Reduce(data, func(min float32, single float32) float32 { - if single < min { - return single - } - return min - }, math.MaxFloat32) - } else if dataType.Kind() == reflect.Float64 { - return Reduce(data, func(min float64, single float64) float64 { - if single < min { - return single - } - return min - }, math.MaxFloat64) - } else { - panic("invalid type " + dataType.String()) +func Min[T Number](data []T) T { + if len(data) == 0 { + panic(fmt.Errorf("data length is 0")) } + return Reduce(data, func(r T, t T) T { + if t < r { + return t + } + return r + }, data[0]) } // Reverse reverse data in table @@ -409,15 +356,12 @@ func Min(data interface{}) interface{} { // []User{}, // ) func Reverse[T any](data []T) []T { - dataValue := reflect.ValueOf(data) - dataType := dataValue.Type() - dataLen := dataValue.Len() - result := reflect.MakeSlice(dataType, dataLen, dataLen) - + dataLen := len(data) + result := make([]T, dataLen, dataLen) for i := 0; i != dataLen; i++ { - result.Index(dataLen - i - 1).Set(dataValue.Index(i)) + result[dataLen-i-1] = data[i] } - return result.Interface().([]T) + return result } // Distinct unique by column diff --git a/query/query_test.go b/query/query_test.go index be0425f..8f1535a 100644 --- a/query/query_test.go +++ b/query/query_test.go @@ -47,6 +47,39 @@ func TestQueryReduce(t *testing.T) { } +func TestQuerySum(t *testing.T) { + testCase := testdata.GetQuerySumTestCase() + + for singleTestCaseIndex, singleTestCase := range testCase { + + assert.Equal(t, singleTestCase.Target, singleTestCase.Handler(), singleTestCaseIndex) + + } + +} + +func TestQueryMax(t *testing.T) { + testCase := testdata.GetQueryMaxTestCase() + + for singleTestCaseIndex, singleTestCase := range testCase { + + assert.Equal(t, singleTestCase.Target, singleTestCase.Handler(), singleTestCaseIndex) + + } + +} + +func TestQueryMin(t *testing.T) { + testCase := testdata.GetQueryMinTestCase() + + for singleTestCaseIndex, singleTestCase := range testCase { + + assert.Equal(t, singleTestCase.Target, singleTestCase.Handler(), singleTestCaseIndex) + + } + +} + func TestQuerySort(t *testing.T) { testCase := testdata.GetQuerySortTestCase() diff --git a/query/test_data/query_case.go b/query/test_data/query_case.go index fe217ca..bd3d1f7 100644 --- a/query/test_data/query_case.go +++ b/query/test_data/query_case.go @@ -414,6 +414,134 @@ func GetQueryReduceTestCase() []TestCase { return testCase } +func GetQuerySumTestCase() []TestCase { + + testCase := []TestCase{ + { + func() interface{} { + return query.Sum( + []int{1, 2, 3, 4, 5}, + ) + }, + 15, + }, + { + func() interface{} { + return query.Sum( + []float32{1.2, 2.3, 4.5, 2.6, 10.9}, + ) + }, + float32(21.5), + }, + { + func() interface{} { + return query.Sum( + []float64{1.2, 2.3, 4.5, 2.6, 10.9, 100000000.200000000}, + ) + }, + 100000021.7, + }, + } + + return testCase +} + +func GetQueryMaxTestCase() []TestCase { + + testCase := []TestCase{ + { + func() interface{} { + return query.Max( + []int{1, 2, 3, 4, 5}, + ) + }, + 5, + }, + { + func() interface{} { + return query.Max( + []int{-1, -2, -3, -4, -5}, + ) + }, + -1, + }, + { + func() interface{} { + return query.Max( + []int{-1, -2, 3, 4, 5}, + ) + }, + 5, + }, + { + func() interface{} { + return query.Max( + []float32{1.2, 2.3, 4.5, 2.6, 10.9}, + ) + }, + float32(10.9), + }, + { + func() interface{} { + return query.Max( + []float64{1.2, 2.3, 4.5, 2.6, 10.9, 100000000.200000000}, + ) + }, + 100000000.2, + }, + } + + return testCase +} + +func GetQueryMinTestCase() []TestCase { + + testCase := []TestCase{ + { + func() interface{} { + return query.Min( + []int{1, 2, 3, 4, 5}, + ) + }, + 1, + }, + { + func() interface{} { + return query.Min( + []int{-1, -2, -3, -4, -5}, + ) + }, + -5, + }, + { + func() interface{} { + return query.Min( + []int{-1, -2, 3, 4, 5}, + ) + }, + -2, + }, + { + func() interface{} { + return query.Min( + []float32{1.2, 2.3, 4.5, 2.6, 10.9}, + ) + }, + float32(1.2), + }, + { + func() interface{} { + return query.Min( + []float64{1.2, 2.3, 4.5, 2.6, 10.9, 100000000.200000000}, + ) + }, + 1.2, + }, + } + + return testCase +} + // GetQuerySortTestCase GetQuerySortTestCase func GetQuerySortTestCase() []TestCase { nowTime := time.Now() @@ -1268,7 +1396,7 @@ func GetQueryGroupTestCase() []TestCase { "Name", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, float32](list, " Money ")) - list[0].Money = sum.(float32) + list[0].Money = sum return []ContentType{list[0]} }) }, @@ -1290,7 +1418,7 @@ func GetQueryGroupTestCase() []TestCase { }, "Name", func(list []ContentType) float32 { - sum := query.Sum(query.Column[ContentType, float32](list, " Money ")).(float32) + sum := query.Sum(query.Column[ContentType, float32](list, " Money ")) return sum }) }, @@ -1309,7 +1437,7 @@ func GetQueryGroupTestCase() []TestCase { "Ok", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, float64](list, "CardMoney ")) - list[0].CardMoney = sum.(float64) + list[0].CardMoney = sum return []ContentType{list[0]} }) }, @@ -1331,7 +1459,7 @@ func GetQueryGroupTestCase() []TestCase { " Age ", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")) - list[0].CardMoney = sum.(float64) + list[0].CardMoney = sum return []ContentType{list[0]} }) }, @@ -1353,7 +1481,7 @@ func GetQueryGroupTestCase() []TestCase { }, " Age ", func(list []ContentType) float64 { - sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")).(float64) + sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")) return sum }) @@ -1373,7 +1501,7 @@ func GetQueryGroupTestCase() []TestCase { " Age ", func(list []ContentType) []float64 { sum := query.Sum(query.Column[ContentType, float64](list, " CardMoney ")) - return []float64{sum.(float64)} + return []float64{sum} }) }, @@ -1392,7 +1520,7 @@ func GetQueryGroupTestCase() []TestCase { "Register ", func(list []ContentType) int { sum := query.Sum(query.Column[ContentType, int](list, " Age ")) - return sum.(int) + return sum }) }, @@ -1411,7 +1539,7 @@ func GetQueryGroupTestCase() []TestCase { "Register ", func(list []ContentType) []ContentType { sum := query.Sum(query.Column[ContentType, int](list, " Age ")) - list[0].Age = sum.(int) + list[0].Age = sum return []ContentType{list[0]} }) }, @@ -1459,7 +1587,7 @@ func GetQueryGroupTestCase() []TestCase { "QueryInnerStruct.MM", func(list []QueryInnerStruct2) []QueryInnerStruct2 { sum := query.Sum(query.Column[QueryInnerStruct2, int](list, " MM ")) - list[0].MM = sum.(int) + list[0].MM = sum return []QueryInnerStruct2{list[0]} }) }, @@ -1484,7 +1612,7 @@ func GetQueryColumnMapTestCase() []TestCase { //querycolumn single { func() interface{} { - return query.ColumnMap[int, int]( + return query.ColumnMap[int, int, map[int]int]( []int{}, " . ") }, @@ -1492,7 +1620,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[string, string]( + return query.ColumnMap[string, string, map[string]string]( []string{"1", "7", "8"}, " . ") }, @@ -1500,7 +1628,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[ContentType, string]( + return query.ColumnMap[ContentType, string, map[string]ContentType]( []ContentType{}, " Name ") }, @@ -1508,7 +1636,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[ContentType, string]( + return query.ColumnMap[ContentType, string, map[string]ContentType]( []ContentType{ {"a", 3, true, 0, 0, nowTime}, {"0", -1, false, 1.1, 1.1, zeroTime}, @@ -1528,7 +1656,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[ContentType, int]( + return query.ColumnMap[ContentType, int, map[int]ContentType]( []ContentType{ {"a", 3, true, 0, 0, nowTime}, {"0", -1, false, 1.1, 1.1, zeroTime}, @@ -1547,7 +1675,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[ContentType, bool]( + return query.ColumnMap[ContentType, bool, map[bool]ContentType]( []ContentType{ {"a", 3, true, 0, 0, nowTime}, {"0", -1, false, 1.1, 1.1, zeroTime}, @@ -1564,7 +1692,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[ContentType, float32]( + return query.ColumnMap[ContentType, float32, map[float32]ContentType]( []ContentType{ {"a", 3, true, 0, 0, nowTime}, {"0", -1, false, 1.1, 1.1, zeroTime}, @@ -1582,7 +1710,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[ContentType, float64]( + return query.ColumnMap[ContentType, float64, map[float64]ContentType]( []ContentType{ {"a", 3, true, 0, 0, nowTime}, {"0", -1, false, 1.1, 1.1, zeroTime}, @@ -1600,7 +1728,7 @@ func GetQueryColumnMapTestCase() []TestCase { }, { func() interface{} { - return query.ColumnMap[QueryInnerStruct2, int]( + return query.ColumnMap[QueryInnerStruct2, int, map[int]QueryInnerStruct2]( []QueryInnerStruct2{ {QueryInnerStruct{1}, 2, 1.1}, {QueryInnerStruct{2}, 4, 2.1}, @@ -1614,161 +1742,161 @@ func GetQueryColumnMapTestCase() []TestCase { 3: {QueryInnerStruct{3}, 5, 3.1}, }, }, - //queryColumn []slice - // { - // func() interface{} { - // return query.ColumnMap( - // []ContentType{}, - // " []Name ") - // }, - // map[string][]ContentType{}, - // }, - // { - // func() interface{} { - // return query.ColumnMap( - // []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // ContentType{"1", -2, false, 0, 0, zeroTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // " [] Name ") - // }, - // map[string][]ContentType{ - // "a": []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // }, - // "0": []ContentType{ - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // }, - // "1": []ContentType{ - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // ContentType{"1", -2, false, 0, 0, zeroTime}, - // }, - // "z": []ContentType{ - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // }, - // }, - // { - // func() interface{} { - // return query.ColumnMap( - // []ContentType{ - // ContentType{"a", 10, true, 0, 0, nowTime}, - // ContentType{"0", 10, false, 1.1, 1.1, zeroTime}, - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // "[]Age ") - // }, - // map[int][]ContentType{ - // 10: []ContentType{ - // ContentType{"a", 10, true, 0, 0, nowTime}, - // ContentType{"0", 10, false, 1.1, 1.1, zeroTime}, - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // }, - // -2: []ContentType{ - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // }, - // 3: []ContentType{ - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // }, - // }, - // { - // func() interface{} { - // return query.ColumnMap( - // []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // "[]Ok ") - // }, - // map[bool][]ContentType{ - // true: []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // false: []ContentType{ - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // }, - // }, - // }, - // { - // func() interface{} { - // return query.ColumnMap( - // []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // " []Money ") - // }, - // map[float32][]ContentType{ - // 0: []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // 1.1: []ContentType{ - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // }, - // -2.2: []ContentType{ - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // }, - // }, - // }, - // { - // func() interface{} { - // return query.ColumnMap( - // []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // " []CardMoney") - // }, - // map[float64][]ContentType{ - // 0: []ContentType{ - // ContentType{"a", 3, true, 0, 0, nowTime}, - // ContentType{"-1", -2, false, 0, 0, zeroTime}, - // ContentType{"z", 3, true, 0, 0, nowTime}, - // }, - // 1.1: []ContentType{ - // ContentType{"0", -1, false, 1.1, 1.1, zeroTime}, - // }, - // -1.2: []ContentType{ - // ContentType{"1", 10, true, -2.2, -1.2, oldTime}, - // }, - // }, - // }, - // { - // func() interface{} { - // return query.ColumnMap( - // []QueryInnerStruct2{ - // QueryInnerStruct2{QueryInnerStruct{1}, 2, 1.1}, - // QueryInnerStruct2{QueryInnerStruct{2}, 4, 2.1}, - // QueryInnerStruct2{QueryInnerStruct{3}, 5, 3.1}, - // }, - // "[]QueryInnerStruct.MM") - // }, - // map[int][]QueryInnerStruct2{ - // 1: []QueryInnerStruct2{QueryInnerStruct2{QueryInnerStruct{1}, 2, 1.1}}, - // 2: []QueryInnerStruct2{QueryInnerStruct2{QueryInnerStruct{2}, 4, 2.1}}, - // 3: []QueryInnerStruct2{QueryInnerStruct2{QueryInnerStruct{3}, 5, 3.1}}, - // }, - // }, + // queryColumn []slice + { + func() interface{} { + return query.ColumnMap[ContentType, string, map[string][]ContentType]( + []ContentType{}, + " []Name ") + }, + map[string][]ContentType{}, + }, + { + func() interface{} { + return query.ColumnMap[ContentType, string, map[string][]ContentType]( + []ContentType{ + {"a", 3, true, 0, 0, nowTime}, + {"0", -1, false, 1.1, 1.1, zeroTime}, + {"1", 10, true, -2.2, -1.2, oldTime}, + {"1", -2, false, 0, 0, zeroTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + " [] Name ") + }, + map[string][]ContentType{ + "a": { + {"a", 3, true, 0, 0, nowTime}, + }, + "0": { + {"0", -1, false, 1.1, 1.1, zeroTime}, + }, + "1": { + {"1", 10, true, -2.2, -1.2, oldTime}, + {"1", -2, false, 0, 0, zeroTime}, + }, + "z": { + {"z", 3, true, 0, 0, nowTime}, + }, + }, + }, + { + func() interface{} { + return query.ColumnMap[ContentType, int, map[int][]ContentType]( + []ContentType{ + {"a", 10, true, 0, 0, nowTime}, + {"0", 10, false, 1.1, 1.1, zeroTime}, + {"1", 10, true, -2.2, -1.2, oldTime}, + {"-1", -2, false, 0, 0, zeroTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + "[]Age ") + }, + map[int][]ContentType{ + 10: { + {"a", 10, true, 0, 0, nowTime}, + {"0", 10, false, 1.1, 1.1, zeroTime}, + {"1", 10, true, -2.2, -1.2, oldTime}, + }, + -2: { + {"-1", -2, false, 0, 0, zeroTime}, + }, + 3: { + {"z", 3, true, 0, 0, nowTime}, + }, + }, + }, + { + func() interface{} { + return query.ColumnMap[ContentType, bool, map[bool][]ContentType]( + []ContentType{ + {"a", 3, true, 0, 0, nowTime}, + {"0", -1, false, 1.1, 1.1, zeroTime}, + {"1", 10, true, -2.2, -1.2, oldTime}, + {"-1", -2, false, 0, 0, zeroTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + "[]Ok ") + }, + map[bool][]ContentType{ + true: { + {"a", 3, true, 0, 0, nowTime}, + {"1", 10, true, -2.2, -1.2, oldTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + false: { + {"0", -1, false, 1.1, 1.1, zeroTime}, + {"-1", -2, false, 0, 0, zeroTime}, + }, + }, + }, + { + func() interface{} { + return query.ColumnMap[ContentType, float32, map[float32][]ContentType]( + []ContentType{ + {"a", 3, true, 0, 0, nowTime}, + {"0", -1, false, 1.1, 1.1, zeroTime}, + {"1", 10, true, -2.2, -1.2, oldTime}, + {"-1", -2, false, 0, 0, zeroTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + " []Money ") + }, + map[float32][]ContentType{ + 0: { + {"a", 3, true, 0, 0, nowTime}, + {"-1", -2, false, 0, 0, zeroTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + 1.1: { + {"0", -1, false, 1.1, 1.1, zeroTime}, + }, + -2.2: { + {"1", 10, true, -2.2, -1.2, oldTime}, + }, + }, + }, + { + func() interface{} { + return query.ColumnMap[ContentType, float64, map[float64][]ContentType]( + []ContentType{ + {"a", 3, true, 0, 0, nowTime}, + {"0", -1, false, 1.1, 1.1, zeroTime}, + {"1", 10, true, -2.2, -1.2, oldTime}, + {"-1", -2, false, 0, 0, zeroTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + " []CardMoney") + }, + map[float64][]ContentType{ + 0: { + {"a", 3, true, 0, 0, nowTime}, + {"-1", -2, false, 0, 0, zeroTime}, + {"z", 3, true, 0, 0, nowTime}, + }, + 1.1: { + {"0", -1, false, 1.1, 1.1, zeroTime}, + }, + -1.2: { + {"1", 10, true, -2.2, -1.2, oldTime}, + }, + }, + }, + { + func() interface{} { + return query.ColumnMap[QueryInnerStruct2, int, map[int][]QueryInnerStruct2]( + []QueryInnerStruct2{ + {QueryInnerStruct{1}, 2, 1.1}, + {QueryInnerStruct{2}, 4, 2.1}, + {QueryInnerStruct{3}, 5, 3.1}, + }, + "[]QueryInnerStruct.MM") + }, + map[int][]QueryInnerStruct2{ + 1: {{QueryInnerStruct{1}, 2, 1.1}}, + 2: {{QueryInnerStruct{2}, 4, 2.1}}, + 3: {{QueryInnerStruct{3}, 5, 3.1}}, + }, + }, } return testCase diff --git a/query/test_data/test_data_querygen.go b/query/test_data/test_data_querygen.go index 6fc310a..770a447 100644 --- a/query/test_data/test_data_querygen.go +++ b/query/test_data/test_data_querygen.go @@ -15,6 +15,48 @@ func queryColumnMapV1634476ac5d81ffe821151e2cd007944bb75387e(data []ContentType, return result } +func queryColumnMapV17413fb3daa269475dd84fbd43de7143d1a1fecd(data []ContentType, column string) map[float32][]ContentType { + dataIn := data + bufferData := make([]ContentType, len(dataIn), len(dataIn)) + mapData := make(map[float32]int, len(dataIn)) + result := make(map[float32][]ContentType, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Money + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].Money] = bufferData[kbegin:k] + + } + + return result +} + func queryColumnMapV3923b792e276005e09637544ecb3aec8be870f41(data []string, column string) map[string]string { dataIn := data result := make(map[string]string, len(dataIn)) @@ -45,6 +87,174 @@ func queryColumnMapV3f666f2858a8335d8dedbc686b034302e2f4fc0f(data []ContentType, return result } +func queryColumnMapV53ba67968a45a6ad0844debe5d0894f3bfbf48a2(data []ContentType, column string) map[float64][]ContentType { + dataIn := data + bufferData := make([]ContentType, len(dataIn), len(dataIn)) + mapData := make(map[float64]int, len(dataIn)) + result := make(map[float64][]ContentType, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].CardMoney + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].CardMoney] = bufferData[kbegin:k] + + } + + return result +} + +func queryColumnMapV68400eb3d8154e355447a3652268b3ee45711762(data []ContentType, column string) map[string][]ContentType { + dataIn := data + bufferData := make([]ContentType, len(dataIn), len(dataIn)) + mapData := make(map[string]int, len(dataIn)) + result := make(map[string][]ContentType, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Name + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].Name] = bufferData[kbegin:k] + + } + + return result +} + +func queryColumnMapV7c828f56cce9605a6545677e43765003f2a1e3da(data []ContentType, column string) map[int][]ContentType { + dataIn := data + bufferData := make([]ContentType, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + result := make(map[int][]ContentType, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Age + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].Age] = bufferData[kbegin:k] + + } + + return result +} + +func queryColumnMapV8388abeb56ba7226a39979e2f85daf5b77b0ec13(data []ContentType, column string) map[string][]ContentType { + dataIn := data + bufferData := make([]ContentType, len(dataIn), len(dataIn)) + mapData := make(map[string]int, len(dataIn)) + result := make(map[string][]ContentType, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Name + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].Name] = bufferData[kbegin:k] + + } + + return result +} + func queryColumnMapV84f666378aff13a68045428e41ef52e9bf17a800(data []QueryInnerStruct2, column string) map[int]QueryInnerStruct2 { dataIn := data result := make(map[int]QueryInnerStruct2, len(dataIn)) @@ -95,6 +305,90 @@ func queryColumnMapV9379e410e09e784ed64aa5e8311734b853ca1260(data []ContentType, return result } +func queryColumnMapVa3c39cd2e6c27da10580768a73066e91af5bfb6c(data []ContentType, column string) map[bool][]ContentType { + dataIn := data + bufferData := make([]ContentType, len(dataIn), len(dataIn)) + mapData := make(map[bool]int, len(dataIn)) + result := make(map[bool][]ContentType, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].Ok + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].Ok] = bufferData[kbegin:k] + + } + + return result +} + +func queryColumnMapVc0d612348cc652ffb28125191e9e18b8956d695f(data []QueryInnerStruct2, column string) map[int][]QueryInnerStruct2 { + dataIn := data + bufferData := make([]QueryInnerStruct2, len(dataIn), len(dataIn)) + mapData := make(map[int]int, len(dataIn)) + result := make(map[int][]QueryInnerStruct2, len(dataIn)) + + length := len(dataIn) + nextData := make([]int, length, length) + for i := 0; i != length; i++ { + single := dataIn[i].QueryInnerStruct.MM + lastIndex, isExist := mapData[single] + if isExist == true { + nextData[lastIndex] = i + } + nextData[i] = -1 + mapData[single] = i + } + k := 0 + for i := 0; i != length; i++ { + j := i + if nextData[j] == 0 { + continue + } + kbegin := k + for nextData[j] != -1 { + nextJ := nextData[j] + bufferData[k] = dataIn[j] + nextData[j] = 0 + j = nextJ + k++ + } + bufferData[k] = dataIn[j] + k++ + nextData[j] = 0 + + result[bufferData[kbegin].QueryInnerStruct.MM] = bufferData[kbegin:k] + + } + + return result +} + func queryColumnV1326c8079077532a2df04e5705513b21ec7ccfde(data []ContentType, column string) []float64 { dataIn := data result := make([]float64, len(dataIn), len(dataIn)) @@ -2076,23 +2370,37 @@ func queryWhereV8dd2f22a7d420700a40e4fb90e0ec144ad4ab02a(data []ContentType, whe func init() { - query.ColumnMapMacroRegister([]ContentType{}, " Name ", queryColumnMapV1634476ac5d81ffe821151e2cd007944bb75387e) + query.ColumnMapMacroRegister[ContentType, string]([]ContentType{}, " Name ", queryColumnMapV1634476ac5d81ffe821151e2cd007944bb75387e) + + query.ColumnMapMacroRegister[ContentType, float32]([]ContentType{}, " []Money ", queryColumnMapV17413fb3daa269475dd84fbd43de7143d1a1fecd) + + query.ColumnMapMacroRegister[string, string]([]string{}, " . ", queryColumnMapV3923b792e276005e09637544ecb3aec8be870f41) + + query.ColumnMapMacroRegister[ContentType, float32]([]ContentType{}, " Money ", queryColumnMapV3c9c70c40c63019848d44a57a05b107340215e80) + + query.ColumnMapMacroRegister[ContentType, float64]([]ContentType{}, " CardMoney", queryColumnMapV3f666f2858a8335d8dedbc686b034302e2f4fc0f) + + query.ColumnMapMacroRegister[ContentType, float64]([]ContentType{}, " []CardMoney", queryColumnMapV53ba67968a45a6ad0844debe5d0894f3bfbf48a2) + + query.ColumnMapMacroRegister[ContentType, string]([]ContentType{}, " []Name ", queryColumnMapV68400eb3d8154e355447a3652268b3ee45711762) + + query.ColumnMapMacroRegister[ContentType, int]([]ContentType{}, "[]Age ", queryColumnMapV7c828f56cce9605a6545677e43765003f2a1e3da) - query.ColumnMapMacroRegister([]string{}, " . ", queryColumnMapV3923b792e276005e09637544ecb3aec8be870f41) + query.ColumnMapMacroRegister[ContentType, string]([]ContentType{}, " [] Name ", queryColumnMapV8388abeb56ba7226a39979e2f85daf5b77b0ec13) - query.ColumnMapMacroRegister([]ContentType{}, " Money ", queryColumnMapV3c9c70c40c63019848d44a57a05b107340215e80) + query.ColumnMapMacroRegister[QueryInnerStruct2, int]([]QueryInnerStruct2{}, "QueryInnerStruct.MM", queryColumnMapV84f666378aff13a68045428e41ef52e9bf17a800) - query.ColumnMapMacroRegister([]ContentType{}, " CardMoney", queryColumnMapV3f666f2858a8335d8dedbc686b034302e2f4fc0f) + query.ColumnMapMacroRegister[ContentType, bool]([]ContentType{}, "Ok ", queryColumnMapV890fbb2d61811a21c543c5d899f2e91b964343eb) - query.ColumnMapMacroRegister([]QueryInnerStruct2{}, "QueryInnerStruct.MM", queryColumnMapV84f666378aff13a68045428e41ef52e9bf17a800) + query.ColumnMapMacroRegister[ContentType, string]([]ContentType{}, " Name ", queryColumnMapV8be389735876e433a498564bd3f63c8f1232d915) - query.ColumnMapMacroRegister([]ContentType{}, "Ok ", queryColumnMapV890fbb2d61811a21c543c5d899f2e91b964343eb) + query.ColumnMapMacroRegister[int, int]([]int{}, " . ", queryColumnMapV91dacd60e87431951940b4b4c51428e7c1e5c1f2) - query.ColumnMapMacroRegister([]ContentType{}, " Name ", queryColumnMapV8be389735876e433a498564bd3f63c8f1232d915) + query.ColumnMapMacroRegister[ContentType, int]([]ContentType{}, "Age ", queryColumnMapV9379e410e09e784ed64aa5e8311734b853ca1260) - query.ColumnMapMacroRegister([]int{}, " . ", queryColumnMapV91dacd60e87431951940b4b4c51428e7c1e5c1f2) + query.ColumnMapMacroRegister[ContentType, bool]([]ContentType{}, "[]Ok ", queryColumnMapVa3c39cd2e6c27da10580768a73066e91af5bfb6c) - query.ColumnMapMacroRegister([]ContentType{}, "Age ", queryColumnMapV9379e410e09e784ed64aa5e8311734b853ca1260) + query.ColumnMapMacroRegister[QueryInnerStruct2, int]([]QueryInnerStruct2{}, "[]QueryInnerStruct.MM", queryColumnMapVc0d612348cc652ffb28125191e9e18b8956d695f) query.ColumnMacroRegister([]ContentType{}, "CardMoney ", queryColumnV1326c8079077532a2df04e5705513b21ec7ccfde)