Compare commits
17 Commits
v1.0.0
...
entgo/v1.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c37d726b4c | ||
|
|
b27c96f932 | ||
|
|
836f4e2461 | ||
|
|
5717d4aefe | ||
|
|
62142a6836 | ||
|
|
9990fa43e0 | ||
|
|
82fbdc15d9 | ||
|
|
b4188ca4d8 | ||
|
|
e9ea8fa536 | ||
|
|
6ed25e948c | ||
|
|
bfea578907 | ||
|
|
b8a6f7f7d8 | ||
|
|
149ded5d4e | ||
|
|
60c0477999 | ||
|
|
ef3aa38cb2 | ||
|
|
498bc3ea18 | ||
|
|
1c225465de |
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/mattn/go-sqlite3"
|
"github.com/mattn/go-sqlite3"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/bank_card/assets"
|
"github.com/tx7do/go-utils/bank_card/assets"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Database struct {
|
type Database struct {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module github.com/tx7do/kratos-utils/bank_card
|
module github.com/tx7do/go-utils/bank_card
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
@@ -12,3 +12,5 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/tx7do/go-utils => ../
|
||||||
|
|||||||
44
byteutil/util.go
Normal file
44
byteutil/util.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package byteutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IntToBytes 将int转换为[]byte
|
||||||
|
func IntToBytes(n int) []byte {
|
||||||
|
data := int64(n)
|
||||||
|
byteBuf := bytes.NewBuffer([]byte{})
|
||||||
|
_ = binary.Write(byteBuf, binary.BigEndian, data)
|
||||||
|
return byteBuf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesToInt 将[]byte转换为int
|
||||||
|
func BytesToInt(bys []byte) int {
|
||||||
|
byteBuf := bytes.NewBuffer(bys)
|
||||||
|
var data int64
|
||||||
|
_ = binary.Read(byteBuf, binary.BigEndian, &data)
|
||||||
|
return int(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByteToLower lowers a byte
|
||||||
|
func ByteToLower(b byte) byte {
|
||||||
|
if b <= '\u007F' {
|
||||||
|
if 'A' <= b && b <= 'Z' {
|
||||||
|
b += 'a' - 'A'
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// ByteToUpper upper a byte
|
||||||
|
func ByteToUpper(b byte) byte {
|
||||||
|
if b <= '\u007F' {
|
||||||
|
if 'a' <= b && b <= 'z' {
|
||||||
|
b -= 'a' - 'A'
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
11
byteutil/util_test.go
Normal file
11
byteutil/util_test.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package byteutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntToBytes(t *testing.T) {
|
||||||
|
fmt.Println(IntToBytes(1))
|
||||||
|
fmt.Println(BytesToInt(IntToBytes(1)))
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
module github.com/tx7do/kratos-utils/entgo
|
module github.com/tx7do/go-utils/entgo
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
@@ -6,9 +6,9 @@ require (
|
|||||||
entgo.io/contrib v0.4.5
|
entgo.io/contrib v0.4.5
|
||||||
entgo.io/ent v0.12.4
|
entgo.io/ent v0.12.4
|
||||||
github.com/go-kratos/kratos/v2 v2.7.1
|
github.com/go-kratos/kratos/v2 v2.7.1
|
||||||
github.com/google/uuid v1.3.1
|
github.com/google/uuid v1.4.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
github.com/tx7do/kratos-utils v0.0.0-20231025044346-36a096df76d8
|
github.com/tx7do/go-utils v1.1.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -25,6 +25,7 @@ require (
|
|||||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/sony/sonyflake v1.2.0 // indirect
|
||||||
github.com/zclconf/go-cty v1.14.1 // indirect
|
github.com/zclconf/go-cty v1.14.1 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/mod v0.13.0 // indirect
|
golang.org/x/mod v0.13.0 // indirect
|
||||||
@@ -34,3 +35,5 @@ require (
|
|||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/tx7do/go-utils => ../
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
|||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
|
github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
|
||||||
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
|
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
|
||||||
github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
|
github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
|
||||||
@@ -42,10 +42,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
|
github.com/sony/sonyflake v1.2.0 h1:Pfr3A+ejSg+0SPqpoAmQgEtNDAhc2G1SUYk205qVMLQ=
|
||||||
|
github.com/sony/sonyflake v1.2.0/go.mod h1:LORtCywH/cq10ZbyfhKrHYgAUGH7mOBa76enV9txy/Y=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/tx7do/kratos-utils v0.0.0-20231025044346-36a096df76d8 h1:G+s0DQ6zI0dGcvd9tRpXcYzelO0xRnp2jpFtQ+697Ko=
|
|
||||||
github.com/tx7do/kratos-utils v0.0.0-20231025044346-36a096df76d8/go.mod h1:rTeeqeABjK9HamIwKZ+uLozVIk/hGiEbNsi6rVr4l0w=
|
|
||||||
github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA=
|
github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA=
|
||||||
github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
|||||||
21
entgo/mixin/creator_id.go
Normal file
21
entgo/mixin/creator_id.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package mixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"entgo.io/ent"
|
||||||
|
"entgo.io/ent/schema/field"
|
||||||
|
_mixin "entgo.io/ent/schema/mixin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreatorId struct {
|
||||||
|
_mixin.Schema
|
||||||
|
}
|
||||||
|
|
||||||
|
func (CreatorId) Fields() []ent.Field {
|
||||||
|
return []ent.Field{
|
||||||
|
field.Uint64("creator_id").
|
||||||
|
Comment("创建者用户ID").
|
||||||
|
Immutable().
|
||||||
|
Optional().
|
||||||
|
Nillable(),
|
||||||
|
}
|
||||||
|
}
|
||||||
37
entgo/mixin/snowflake_id.go
Normal file
37
entgo/mixin/snowflake_id.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package mixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"entgo.io/ent"
|
||||||
|
"entgo.io/ent/dialect"
|
||||||
|
"entgo.io/ent/schema/field"
|
||||||
|
"entgo.io/ent/schema/index"
|
||||||
|
"entgo.io/ent/schema/mixin"
|
||||||
|
|
||||||
|
"github.com/tx7do/go-utils/sonyflake"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SnowflackId struct {
|
||||||
|
mixin.Schema
|
||||||
|
}
|
||||||
|
|
||||||
|
func (SnowflackId) Fields() []ent.Field {
|
||||||
|
return []ent.Field{
|
||||||
|
field.Uint64("id").
|
||||||
|
Comment("id").
|
||||||
|
DefaultFunc(sonyflake.GenerateSonyflake).
|
||||||
|
Positive().
|
||||||
|
Immutable().
|
||||||
|
StructTag(`json:"id,omitempty"`).
|
||||||
|
SchemaType(map[string]string{
|
||||||
|
dialect.MySQL: "bigint",
|
||||||
|
dialect.Postgres: "bigint",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indexes of the SnowflackId.
|
||||||
|
func (SnowflackId) Indexes() []ent.Index {
|
||||||
|
return []ent.Index{
|
||||||
|
index.Fields("id"),
|
||||||
|
}
|
||||||
|
}
|
||||||
33
entgo/mixin/string_id.go
Normal file
33
entgo/mixin/string_id.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package mixin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"entgo.io/ent"
|
||||||
|
"entgo.io/ent/schema/field"
|
||||||
|
"entgo.io/ent/schema/index"
|
||||||
|
"entgo.io/ent/schema/mixin"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StringId struct {
|
||||||
|
mixin.Schema
|
||||||
|
}
|
||||||
|
|
||||||
|
func (StringId) Fields() []ent.Field {
|
||||||
|
return []ent.Field{
|
||||||
|
field.String("id").
|
||||||
|
Comment("id").
|
||||||
|
MaxLen(25).
|
||||||
|
NotEmpty().
|
||||||
|
Unique().
|
||||||
|
Immutable().
|
||||||
|
Match(regexp.MustCompile("^[0-9a-zA-Z_\\-]+$")).
|
||||||
|
StructTag(`json:"id,omitempty"`),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indexes of the StringId.
|
||||||
|
func (StringId) Indexes() []ent.Index {
|
||||||
|
return []ent.Index{
|
||||||
|
index.Fields("id"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ func (SwitchStatus) Fields() []ent.Field {
|
|||||||
// dialect.MySQL: "switch_status",
|
// dialect.MySQL: "switch_status",
|
||||||
// dialect.Postgres: "switch_status",
|
// dialect.Postgres: "switch_status",
|
||||||
//}).
|
//}).
|
||||||
|
Default("ON").
|
||||||
Values(
|
Values(
|
||||||
"OFF",
|
"OFF",
|
||||||
"ON",
|
"ON",
|
||||||
|
|||||||
@@ -69,11 +69,11 @@ func (TimeAt) Fields() []ent.Field {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var _ ent.Mixin = (*CreatedTime)(nil)
|
var _ ent.Mixin = (*CreateTime)(nil)
|
||||||
|
|
||||||
type CreatedTime struct{ mixin.Schema }
|
type CreateTime struct{ mixin.Schema }
|
||||||
|
|
||||||
func (CreatedTime) Fields() []ent.Field {
|
func (CreateTime) Fields() []ent.Field {
|
||||||
return []ent.Field{
|
return []ent.Field{
|
||||||
// 创建时间
|
// 创建时间
|
||||||
field.Time("create_time").
|
field.Time("create_time").
|
||||||
@@ -86,11 +86,11 @@ func (CreatedTime) Fields() []ent.Field {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var _ ent.Mixin = (*UpdatedTime)(nil)
|
var _ ent.Mixin = (*UpdateTime)(nil)
|
||||||
|
|
||||||
type UpdatedTime struct{ mixin.Schema }
|
type UpdateTime struct{ mixin.Schema }
|
||||||
|
|
||||||
func (UpdatedTime) Fields() []ent.Field {
|
func (UpdateTime) Fields() []ent.Field {
|
||||||
return []ent.Field{
|
return []ent.Field{
|
||||||
// 更新时间
|
// 更新时间
|
||||||
field.Time("update_time").
|
field.Time("update_time").
|
||||||
@@ -102,11 +102,11 @@ func (UpdatedTime) Fields() []ent.Field {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var _ ent.Mixin = (*DeletedTime)(nil)
|
var _ ent.Mixin = (*DeleteTime)(nil)
|
||||||
|
|
||||||
type DeletedTime struct{ mixin.Schema }
|
type DeleteTime struct{ mixin.Schema }
|
||||||
|
|
||||||
func (DeletedTime) Fields() []ent.Field {
|
func (DeleteTime) Fields() []ent.Field {
|
||||||
return []ent.Field{
|
return []ent.Field{
|
||||||
// 删除时间
|
// 删除时间
|
||||||
field.Time("delete_time").
|
field.Time("delete_time").
|
||||||
@@ -122,9 +122,9 @@ type Time struct{ mixin.Schema }
|
|||||||
|
|
||||||
func (Time) Fields() []ent.Field {
|
func (Time) Fields() []ent.Field {
|
||||||
var fields []ent.Field
|
var fields []ent.Field
|
||||||
fields = append(fields, CreatedTime{}.Fields()...)
|
fields = append(fields, CreateTime{}.Fields()...)
|
||||||
fields = append(fields, UpdatedTime{}.Fields()...)
|
fields = append(fields, UpdateTime{}.Fields()...)
|
||||||
fields = append(fields, DeletedTime{}.Fields()...)
|
fields = append(fields, DeleteTime{}.Fields()...)
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package mixin
|
package mixin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"entgo.io/ent"
|
"entgo.io/ent"
|
||||||
"entgo.io/ent/schema/field"
|
"entgo.io/ent/schema/field"
|
||||||
"entgo.io/ent/schema/mixin"
|
"entgo.io/ent/schema/mixin"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -74,3 +75,71 @@ func (Timestamp) Fields() []ent.Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var _ ent.Mixin = (*CreatedAtTimestamp)(nil)
|
||||||
|
|
||||||
|
type CreatedAtTimestamp struct{ mixin.Schema }
|
||||||
|
|
||||||
|
func (CreatedAtTimestamp) Fields() []ent.Field {
|
||||||
|
return []ent.Field{
|
||||||
|
// 创建时间,毫秒
|
||||||
|
field.Int64("created_at").
|
||||||
|
Comment("创建时间").
|
||||||
|
Immutable().
|
||||||
|
Optional().
|
||||||
|
Nillable().
|
||||||
|
DefaultFunc(time.Now().UnixMilli),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var _ ent.Mixin = (*UpdatedAtTimestamp)(nil)
|
||||||
|
|
||||||
|
type UpdatedAtTimestamp struct{ mixin.Schema }
|
||||||
|
|
||||||
|
func (UpdatedAtTimestamp) Fields() []ent.Field {
|
||||||
|
return []ent.Field{
|
||||||
|
// 更新时间,毫秒
|
||||||
|
// 需要注意的是,如果不是程序自动更新,那么这个字段不会被更新,除非在数据库里面下触发器更新。
|
||||||
|
field.Int64("updated_at").
|
||||||
|
Comment("更新时间").
|
||||||
|
Optional().
|
||||||
|
Nillable().
|
||||||
|
UpdateDefault(time.Now().UnixMilli),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var _ ent.Mixin = (*DeletedAtTimestamp)(nil)
|
||||||
|
|
||||||
|
type DeletedAtTimestamp struct{ mixin.Schema }
|
||||||
|
|
||||||
|
func (DeletedAtTimestamp) Fields() []ent.Field {
|
||||||
|
return []ent.Field{
|
||||||
|
// 删除时间,毫秒
|
||||||
|
field.Int64("deleted_at").
|
||||||
|
Comment("删除时间").
|
||||||
|
Optional().
|
||||||
|
Nillable(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var _ ent.Mixin = (*TimestampAt)(nil)
|
||||||
|
|
||||||
|
type TimestampAt struct{ mixin.Schema }
|
||||||
|
|
||||||
|
func (TimestampAt) Fields() []ent.Field {
|
||||||
|
var fields []ent.Field
|
||||||
|
fields = append(fields, CreatedAtTimestamp{}.Fields()...)
|
||||||
|
fields = append(fields, UpdatedAtTimestamp{}.Fields()...)
|
||||||
|
fields = append(fields, DeletedAtTimestamp{}.Fields()...)
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
## 通用列表查询请求
|
## 通用列表查询请求
|
||||||
|
|
||||||
| 字段名 | 类型 | 格式 | 字段描述 | 示例 | 备注 |
|
| 字段名 | 类型 | 格式 | 字段描述 | 示例 | 备注 |
|
||||||
|----------|-----------|-------------------------------------|---------|----------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
|
|-----------|-----------|-------------------------------------|---------|----------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
|
||||||
| page | `number` | | 当前页码 | | 默认为`1`,最小值为`1`。 |
|
| page | `number` | | 当前页码 | | 默认为`1`,最小值为`1`。 |
|
||||||
| pageSize | `number` | | 每页的行数 | | 默认为`10`,最小值为`1`。 |
|
| pageSize | `number` | | 每页的行数 | | 默认为`10`,最小值为`1`。 |
|
||||||
| query | `string` | `json object` 或 `json object array` | AND过滤条件 | json字符串: `{"field1":"val1","field2":"val2"}` 或者`[{"field1":"val1"},{"field1":"val2"},{"field2":"val2"}]` | `map`和`array`都支持,当需要同字段名,不同值的情况下,请使用`array`。具体规则请见:[过滤规则](#过滤规则) |
|
| query | `string` | `json object` 或 `json object array` | AND过滤条件 | json字符串: `{"field1":"val1","field2":"val2"}` 或者`[{"field1":"val1"},{"field1":"val2"},{"field2":"val2"}]` | `map`和`array`都支持,当需要同字段名,不同值的情况下,请使用`array`。具体规则请见:[过滤规则](#过滤规则) |
|
||||||
| or | `string` | `json object` 或 `json object array` | OR过滤条件 | 同 AND过滤条件 | |
|
| or | `string` | `json object` 或 `json object array` | OR过滤条件 | 同 AND过滤条件 | |
|
||||||
| orderBy | `string` | `json string array` | 排序条件 | json字符串:`["-create_time", "type"]` | json的`string array`,字段名前加`-`是为降序,不加为升序。具体规则请见:[排序规则](#排序规则) |
|
| orderBy | `string` | `json string array` | 排序条件 | json字符串:`["-create_time", "type"]` | json的`string array`,字段名前加`-`是为降序,不加为升序。具体规则请见:[排序规则](#排序规则) |
|
||||||
| nopaging | `boolean` | | 是否不分页 | | 此字段为`true`时,`page`、`pageSize`字段的传入将无效用。 |
|
| nopaging | `boolean` | | 是否不分页 | | 此字段为`true`时,`page`、`pageSize`字段的传入将无效用。 |
|
||||||
|
| fieldMask | `string` | `json string array` | 字段掩码 | | 此字段是`SELECT`条件,为空的时候是为`*`。 |
|
||||||
|
|
||||||
## 排序规则
|
## 排序规则
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"entgo.io/ent/dialect"
|
||||||
"entgo.io/ent/dialect/sql"
|
"entgo.io/ent/dialect/sql"
|
||||||
|
|
||||||
"github.com/go-kratos/kratos/v2/encoding"
|
"github.com/go-kratos/kratos/v2/encoding"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/stringcase"
|
"github.com/tx7do/go-utils/stringcase"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FilterOp int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FilterNot = "not" // 不等于
|
FilterNot = "not" // 不等于
|
||||||
FilterIn = "in" // 检查值是否在列表中
|
FilterIn = "in" // 检查值是否在列表中
|
||||||
@@ -34,23 +38,51 @@ const (
|
|||||||
FilterSearch = "search" // 全文搜索
|
FilterSearch = "search" // 全文搜索
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DatePart int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FilterDatePartDate = "date" // 日期
|
DatePartDate DatePart = iota // 日期
|
||||||
FilterDatePartYear = "year" // 年
|
DatePartYear // 年
|
||||||
FilterDatePartISOYear = "iso_year" // ISO 8601 一年中的周数
|
DatePartISOYear // ISO 8601 一年中的周数
|
||||||
FilterDatePartQuarter = "quarter" // 季度
|
DatePartQuarter // 季度
|
||||||
FilterDatePartMonth = "month" // 月
|
DatePartMonth // 月
|
||||||
FilterDatePartWeek = "week" // ISO 8601 周编号 一年中的周数
|
DatePartWeek // ISO 8601 周编号 一年中的周数
|
||||||
FilterDatePartWeekDay = "week_day" // 星期几
|
DatePartWeekDay // 星期几
|
||||||
FilterDatePartISOWeekDay = "iso_week_day" // 星期几
|
DatePartISOWeekDay // 星期几
|
||||||
FilterDatePartDay = "day" // 日
|
DatePartDay // 日
|
||||||
FilterDatePartTime = "time" // 小时:分钟:秒
|
DatePartTime // 小时:分钟:秒
|
||||||
FilterDatePartHour = "hour" // 小时
|
DatePartHour // 小时
|
||||||
FilterDatePartMinute = "minute" // 分钟
|
DatePartMinute // 分钟
|
||||||
FilterDatePartSecond = "second" // 秒
|
DatePartSecond // 秒
|
||||||
FilterDatePartMicrosecond = "microsecond" // 微秒
|
DatePartMicrosecond // 微秒
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var dateParts = [...]string{
|
||||||
|
DatePartDate: "date",
|
||||||
|
DatePartYear: "year",
|
||||||
|
DatePartISOYear: "iso_year",
|
||||||
|
DatePartQuarter: "quarter",
|
||||||
|
DatePartMonth: "month",
|
||||||
|
DatePartWeek: "week",
|
||||||
|
DatePartWeekDay: "week_day",
|
||||||
|
DatePartISOWeekDay: "iso_week_day",
|
||||||
|
DatePartDay: "day",
|
||||||
|
DatePartTime: "time",
|
||||||
|
DatePartHour: "hour",
|
||||||
|
DatePartMinute: "minute",
|
||||||
|
DatePartSecond: "second",
|
||||||
|
DatePartMicrosecond: "microsecond",
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasDatePart(str string) bool {
|
||||||
|
for _, item := range dateParts {
|
||||||
|
if str == item {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// QueryCommandToWhereConditions 查询命令转换为选择条件
|
// QueryCommandToWhereConditions 查询命令转换为选择条件
|
||||||
func QueryCommandToWhereConditions(strJson string, isOr bool) (error, func(s *sql.Selector)) {
|
func QueryCommandToWhereConditions(strJson string, isOr bool) (error, func(s *sql.Selector)) {
|
||||||
if len(strJson) == 0 {
|
if len(strJson) == 0 {
|
||||||
@@ -154,7 +186,7 @@ func oneFieldFilter(s *sql.Selector, keys []string, value string) *sql.Predicate
|
|||||||
case FilterIsNull:
|
case FilterIsNull:
|
||||||
cond = filterIsNull(s, field, value)
|
cond = filterIsNull(s, field, value)
|
||||||
case FilterNotIsNull:
|
case FilterNotIsNull:
|
||||||
cond = filterNotIsNull(s, field, value)
|
cond = filterIsNotNull(s, field, value)
|
||||||
case FilterContains:
|
case FilterContains:
|
||||||
cond = filterContains(s, field, value)
|
cond = filterContains(s, field, value)
|
||||||
case FilterInsensitiveContains:
|
case FilterInsensitiveContains:
|
||||||
@@ -201,32 +233,20 @@ func filterNot(s *sql.Selector, field, value string) *sql.Predicate {
|
|||||||
// filterIn IN操作
|
// filterIn IN操作
|
||||||
// SQL: WHERE name IN ("tom", "jimmy")
|
// SQL: WHERE name IN ("tom", "jimmy")
|
||||||
func filterIn(s *sql.Selector, field, value string) *sql.Predicate {
|
func filterIn(s *sql.Selector, field, value string) *sql.Predicate {
|
||||||
var strs []string
|
var values []any
|
||||||
if err := json.Unmarshal([]byte(value), &strs); err == nil {
|
if err := json.Unmarshal([]byte(value), &values); err == nil {
|
||||||
return sql.In(s.C(field), strs)
|
return sql.In(s.C(field), values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var float64s []float64
|
|
||||||
if err := json.Unmarshal([]byte(value), &float64s); err == nil {
|
|
||||||
return sql.In(s.C(field), strs)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterNotIn NOT IN操作
|
// filterNotIn NOT IN操作
|
||||||
// SQL: WHERE name NOT IN ("tom", "jimmy")`
|
// SQL: WHERE name NOT IN ("tom", "jimmy")`
|
||||||
func filterNotIn(s *sql.Selector, field, value string) *sql.Predicate {
|
func filterNotIn(s *sql.Selector, field, value string) *sql.Predicate {
|
||||||
var strs []string
|
var values []any
|
||||||
if err := json.Unmarshal([]byte(value), &strs); err == nil {
|
if err := json.Unmarshal([]byte(value), &values); err == nil {
|
||||||
return sql.NotIn(s.C(field), strs)
|
return sql.NotIn(s.C(field), values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var float64s []float64
|
|
||||||
if err := json.Unmarshal([]byte(value), &float64s); err == nil {
|
|
||||||
return sql.NotIn(s.C(field), strs)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,27 +278,15 @@ func filterLT(s *sql.Selector, field, value string) *sql.Predicate {
|
|||||||
// SQL: WHERE "create_time" BETWEEN "2023-10-25" AND "2024-10-25"
|
// SQL: WHERE "create_time" BETWEEN "2023-10-25" AND "2024-10-25"
|
||||||
// 或者: WHERE "create_time" >= "2023-10-25" AND "create_time" <= "2024-10-25"
|
// 或者: WHERE "create_time" >= "2023-10-25" AND "create_time" <= "2024-10-25"
|
||||||
func filterRange(s *sql.Selector, field, value string) *sql.Predicate {
|
func filterRange(s *sql.Selector, field, value string) *sql.Predicate {
|
||||||
var strs []string
|
var values []any
|
||||||
if err := json.Unmarshal([]byte(value), &strs); err == nil {
|
if err := json.Unmarshal([]byte(value), &values); err == nil {
|
||||||
if len(strs) != 2 {
|
if len(values) != 2 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return sql.And(
|
return sql.And(
|
||||||
sql.GTE(s.C(field), strs[0]),
|
sql.GTE(s.C(field), values[0]),
|
||||||
sql.LTE(s.C(field), strs[1]),
|
sql.LTE(s.C(field), values[1]),
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var float64s []float64
|
|
||||||
if err := json.Unmarshal([]byte(value), &float64s); err == nil {
|
|
||||||
if len(float64s) != 2 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return sql.And(
|
|
||||||
sql.GTE(s.C(field), float64s[0]),
|
|
||||||
sql.LTE(s.C(field), float64s[1]),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,9 +299,9 @@ func filterIsNull(s *sql.Selector, field, _ string) *sql.Predicate {
|
|||||||
return sql.IsNull(s.C(field))
|
return sql.IsNull(s.C(field))
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterNotIsNull 不为空 IS NOT NULL操作
|
// filterIsNotNull 不为空 IS NOT NULL操作
|
||||||
// SQL: WHERE name IS NOT NULL
|
// SQL: WHERE name IS NOT NULL
|
||||||
func filterNotIsNull(s *sql.Selector, field, _ string) *sql.Predicate {
|
func filterIsNotNull(s *sql.Selector, field, _ string) *sql.Predicate {
|
||||||
return sql.Not(sql.IsNull(s.C(field)))
|
return sql.Not(sql.IsNull(s.C(field)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,27 +353,75 @@ func filterInsensitiveExact(s *sql.Selector, field, value string) *sql.Predicate
|
|||||||
return sql.EqualFold(s.C(field), value)
|
return sql.EqualFold(s.C(field), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterRegex LIKE 操作 精确比对
|
// filterRegex 正则查找
|
||||||
// MySQL: WHERE title REGEXP BINARY '^(An?|The) +'
|
// MySQL: WHERE title REGEXP BINARY '^(An?|The) +'
|
||||||
// Oracle: WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c');
|
// Oracle: WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c');
|
||||||
// PostgreSQL: WHERE title ~ '^(An?|The) +';
|
// PostgreSQL: WHERE title ~ '^(An?|The) +';
|
||||||
// SQLite: WHERE title REGEXP '^(An?|The) +';
|
// SQLite: WHERE title REGEXP '^(An?|The) +';
|
||||||
func filterRegex(s *sql.Selector, field, value string) *sql.Predicate {
|
func filterRegex(s *sql.Selector, field, value string) *sql.Predicate {
|
||||||
return nil
|
p := sql.P()
|
||||||
|
p.Append(func(b *sql.Builder) {
|
||||||
|
switch s.Builder.Dialect() {
|
||||||
|
case dialect.Postgres:
|
||||||
|
b.Ident(s.C(field)).WriteString(" ~ ")
|
||||||
|
b.Arg(value)
|
||||||
|
break
|
||||||
|
case dialect.MySQL:
|
||||||
|
b.Ident(s.C(field)).WriteString(" REGEXP BINARY ")
|
||||||
|
b.Arg(value)
|
||||||
|
break
|
||||||
|
case dialect.SQLite:
|
||||||
|
b.Ident(s.C(field)).WriteString(" REGEXP ")
|
||||||
|
b.Arg(value)
|
||||||
|
break
|
||||||
|
case dialect.Gremlin:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterInsensitiveRegex ILIKE 操作 不区分大小写,精确比对
|
// filterInsensitiveRegex 正则查找 不区分大小写
|
||||||
// MySQL: WHERE title REGEXP '^(an?|the) +'
|
// MySQL: WHERE title REGEXP '^(an?|the) +'
|
||||||
// Oracle: WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i');
|
// Oracle: WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i');
|
||||||
// PostgreSQL: WHERE title ~* '^(an?|the) +';
|
// PostgreSQL: WHERE title ~* '^(an?|the) +';
|
||||||
// SQLite: WHERE title REGEXP '(?i)^(an?|the) +';
|
// SQLite: WHERE title REGEXP '(?i)^(an?|the) +';
|
||||||
func filterInsensitiveRegex(s *sql.Selector, field, value string) *sql.Predicate {
|
func filterInsensitiveRegex(s *sql.Selector, field, value string) *sql.Predicate {
|
||||||
return nil
|
p := sql.P()
|
||||||
|
p.Append(func(b *sql.Builder) {
|
||||||
|
switch s.Builder.Dialect() {
|
||||||
|
case dialect.Postgres:
|
||||||
|
b.Ident(s.C(field)).WriteString(" ~* ")
|
||||||
|
b.Arg(strings.ToLower(value))
|
||||||
|
break
|
||||||
|
case dialect.MySQL:
|
||||||
|
b.Ident(s.C(field)).WriteString(" REGEXP ")
|
||||||
|
b.Arg(strings.ToLower(value))
|
||||||
|
break
|
||||||
|
case dialect.SQLite:
|
||||||
|
b.Ident(s.C(field)).WriteString(" REGEXP ")
|
||||||
|
if !strings.HasPrefix(value, "(?i)") {
|
||||||
|
value = "(?i)" + value
|
||||||
|
}
|
||||||
|
b.Arg(strings.ToLower(value))
|
||||||
|
break
|
||||||
|
case dialect.Gremlin:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// filterSearch 全文搜索
|
// filterSearch 全文搜索
|
||||||
// SQL:
|
// SQL:
|
||||||
func filterSearch(s *sql.Selector, _, _ string) *sql.Predicate {
|
func filterSearch(s *sql.Selector, _, _ string) *sql.Predicate {
|
||||||
|
p := sql.P()
|
||||||
|
p.Append(func(b *sql.Builder) {
|
||||||
|
switch s.Builder.Dialect() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
541
entgo/query/filter_test.go
Normal file
541
entgo/query/filter_test.go
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
package entgo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"entgo.io/ent/dialect"
|
||||||
|
"entgo.io/ent/dialect/sql"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilter(t *testing.T) {
|
||||||
|
t.Run("MySQL_FilterEqual", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterEqual(s, "name", "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` = ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterEqual", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterEqual(s, "name", "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" = $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterNot", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterNot(s, "name", "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE NOT (`users`.`name` = ?)", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterNot", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterNot(s, "name", "tom")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE NOT (\"users\".\"name\" = $1)", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterIn", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterIn(s, "name", "[\"tom\", \"jimmy\", 123]")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` IN (?, ?, ?)", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
require.Equal(t, args[1], "jimmy")
|
||||||
|
require.Equal(t, args[2], float64(123))
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterIn", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterIn(s, "name", "[\"tom\", \"jimmy\", 123]")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" IN ($1, $2, $3)", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
require.Equal(t, args[1], "jimmy")
|
||||||
|
require.Equal(t, args[2], float64(123))
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterNotIn", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterNotIn(s, "name", "[\"tom\", \"jimmy\", 123]")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` NOT IN (?, ?, ?)", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
require.Equal(t, args[1], "jimmy")
|
||||||
|
require.Equal(t, args[2], float64(123))
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterNotIn", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterNotIn(s, "name", "[\"tom\", \"jimmy\", 123]")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" NOT IN ($1, $2, $3)", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "tom")
|
||||||
|
require.Equal(t, args[1], "jimmy")
|
||||||
|
require.Equal(t, args[2], float64(123))
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterGTE", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterGTE(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`create_time` >= ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterGTE", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterGTE(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"create_time\" >= $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterGT", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterGT(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`create_time` > ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterGT", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterGT(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"create_time\" > $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterLTE", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterLTE(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`create_time` <= ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterLTE", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterLTE(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"create_time\" <= $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterLT", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterLT(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`create_time` < ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterLT", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterLT(s, "create_time", "2023-10-25")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"create_time\" < $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterRange", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterRange(s, "create_time", "[\"2023-10-25\", \"2024-10-25\"]")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`create_time` >= ? AND `users`.`create_time` <= ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
require.Equal(t, args[1], "2024-10-25")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterRange", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterRange(s, "create_time", "[\"2023-10-25\", \"2024-10-25\"]")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"create_time\" >= $1 AND \"users\".\"create_time\" <= $2", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "2023-10-25")
|
||||||
|
require.Equal(t, args[1], "2024-10-25")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterIsNull", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterIsNull(s, "name", "true")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` IS NULL", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterIsNull", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterIsNull(s, "name", "true")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" IS NULL", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterIsNotNull", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterIsNotNull(s, "name", "true")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE NOT (`users`.`name` IS NULL)", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterIsNotNull", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterIsNotNull(s, "name", "true")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE NOT (\"users\".\"name\" IS NULL)", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterContains", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterContains(s, "name", "L")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` LIKE ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "%L%")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterContains", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterContains(s, "name", "L")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" LIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "%L%")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterInsensitiveContains", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveContains(s, "name", "L")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` COLLATE utf8mb4_general_ci LIKE ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "%l%")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterInsensitiveContains", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveContains(s, "name", "L")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" ILIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "%l%")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterStartsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterStartsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` LIKE ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "La%")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterStartsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterStartsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" LIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "La%")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterInsensitiveStartsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveStartsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` COLLATE utf8mb4_general_ci = ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "la%")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterInsensitiveStartsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveStartsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" ILIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "la\\%")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterEndsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterEndsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` LIKE ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "%La")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterEndsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterEndsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" LIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "%La")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterInsensitiveEndsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveEndsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` COLLATE utf8mb4_general_ci = ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "%la")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterInsensitiveEndsWith", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveEndsWith(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" ILIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "\\%la")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterExact", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterExact(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` LIKE ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "La")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterExact", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterExact(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" LIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "La")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterInsensitiveExact", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveExact(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` COLLATE utf8mb4_general_ci = ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "la")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterInsensitiveExact", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveExact(s, "name", "La")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" ILIKE $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "la")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterRegex", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterRegex(s, "name", "^(An?|The) +")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` REGEXP BINARY ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "^(An?|The) +")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterRegex", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterRegex(s, "name", "^(An?|The) +")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" ~ $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "^(An?|The) +")
|
||||||
|
})
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
t.Run("MySQL_FilterInsensitiveRegex", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveRegex(s, "name", "^(An?|The) +")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` WHERE `users`.`name` REGEXP ?", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "^(an?|the) +")
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_FilterInsensitiveRegex", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
p := filterInsensitiveRegex(s, "name", "^(An?|The) +")
|
||||||
|
s.Where(p)
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" WHERE \"users\".\"name\" ~* $1", query)
|
||||||
|
require.NotEmpty(t, args)
|
||||||
|
require.Equal(t, args[0], "^(an?|the) +")
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -21,14 +21,14 @@ func QueryCommandToOrderConditions(orderBys []string) (error, func(s *sql.Select
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s.OrderBy(sql.Desc(s.C(key)))
|
BuildOrderSelect(s, key, true)
|
||||||
} else {
|
} else {
|
||||||
// 升序
|
// 升序
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s.OrderBy(sql.Asc(s.C(v)))
|
BuildOrderSelect(s, v, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,9 +37,17 @@ func QueryCommandToOrderConditions(orderBys []string) (error, func(s *sql.Select
|
|||||||
func BuildOrderSelector(orderBys []string, defaultOrderField string) (error, func(s *sql.Selector)) {
|
func BuildOrderSelector(orderBys []string, defaultOrderField string) (error, func(s *sql.Selector)) {
|
||||||
if len(orderBys) == 0 {
|
if len(orderBys) == 0 {
|
||||||
return nil, func(s *sql.Selector) {
|
return nil, func(s *sql.Selector) {
|
||||||
s.OrderBy(sql.Desc(s.C(defaultOrderField)))
|
BuildOrderSelect(s, defaultOrderField, true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return QueryCommandToOrderConditions(orderBys)
|
return QueryCommandToOrderConditions(orderBys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildOrderSelect(s *sql.Selector, field string, desc bool) {
|
||||||
|
if desc {
|
||||||
|
s.OrderBy(sql.Desc(s.C(field)))
|
||||||
|
} else {
|
||||||
|
s.OrderBy(sql.Asc(s.C(field)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,24 +3,27 @@ package entgo
|
|||||||
import (
|
import (
|
||||||
"entgo.io/ent/dialect/sql"
|
"entgo.io/ent/dialect/sql"
|
||||||
|
|
||||||
paging "github.com/tx7do/kratos-utils/pagination"
|
paging "github.com/tx7do/go-utils/pagination"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BuildPaginationSelector(page, pageSize int32, noPaging bool) func(*sql.Selector) {
|
func BuildPaginationSelector(page, pageSize int32, noPaging bool) func(*sql.Selector) {
|
||||||
if noPaging {
|
if noPaging {
|
||||||
return nil
|
return nil
|
||||||
}
|
} else {
|
||||||
|
return func(s *sql.Selector) {
|
||||||
if page == 0 {
|
BuildPaginationSelect(s, page, pageSize)
|
||||||
page = DefaultPage
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if pageSize == 0 {
|
|
||||||
pageSize = DefaultPageSize
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(s *sql.Selector) {
|
|
||||||
s.Offset(paging.GetPageOffset(page, pageSize)).
|
|
||||||
Limit(int(pageSize))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildPaginationSelect(s *sql.Selector, page, pageSize int32) {
|
||||||
|
if page < 1 {
|
||||||
|
page = paging.DefaultPage
|
||||||
|
}
|
||||||
|
|
||||||
|
if pageSize < 1 {
|
||||||
|
pageSize = paging.DefaultPageSize
|
||||||
|
}
|
||||||
|
offset := paging.GetPageOffset(page, pageSize)
|
||||||
|
s.Offset(offset).Limit(int(pageSize))
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,14 +5,8 @@ import (
|
|||||||
_ "github.com/go-kratos/kratos/v2/encoding/json"
|
_ "github.com/go-kratos/kratos/v2/encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// BuildQuerySelector 构建分页过滤查询器
|
||||||
DefaultPage = 1
|
|
||||||
DefaultPageSize = 10
|
|
||||||
)
|
|
||||||
|
|
||||||
// BuildQuerySelector 构建分页查询选择器
|
|
||||||
func BuildQuerySelector(
|
func BuildQuerySelector(
|
||||||
dbDriverName string,
|
|
||||||
andFilterJsonString, orFilterJsonString string,
|
andFilterJsonString, orFilterJsonString string,
|
||||||
page, pageSize int32, noPaging bool,
|
page, pageSize int32, noPaging bool,
|
||||||
orderBys []string, defaultOrderField string,
|
orderBys []string, defaultOrderField string,
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"entgo.io/ent/dialect"
|
||||||
|
"entgo.io/ent/dialect/sql"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/go-kratos/kratos/v2/encoding"
|
"github.com/go-kratos/kratos/v2/encoding"
|
||||||
_ "github.com/go-kratos/kratos/v2/encoding/json"
|
_ "github.com/go-kratos/kratos/v2/encoding/json"
|
||||||
@@ -92,3 +96,83 @@ func TestSplitQuery(t *testing.T) {
|
|||||||
assert.Equal(t, keys[0], "id")
|
assert.Equal(t, keys[0], "id")
|
||||||
assert.Equal(t, keys[1], "not")
|
assert.Equal(t, keys[1], "not")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildQuerySelectorDefault(t *testing.T) {
|
||||||
|
t.Run("MySQL_Pagination", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
err, whereSelectors, querySelectors := BuildQuerySelector("", "", 1, 10, false, []string{}, "created_at")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Nil(t, whereSelectors)
|
||||||
|
require.NotNil(t, querySelectors)
|
||||||
|
|
||||||
|
for _, fnc := range whereSelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
for _, fnc := range querySelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` ORDER BY `users`.`created_at` DESC LIMIT 10 OFFSET 0", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_Pagination", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
err, whereSelectors, querySelectors := BuildQuerySelector("", "", 1, 10, false, []string{}, "created_at")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Nil(t, whereSelectors)
|
||||||
|
require.NotNil(t, querySelectors)
|
||||||
|
|
||||||
|
for _, fnc := range whereSelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
for _, fnc := range querySelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" ORDER BY \"users\".\"created_at\" DESC LIMIT 10 OFFSET 0", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("MySQL_NoPagination", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.MySQL).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
err, whereSelectors, querySelectors := BuildQuerySelector("", "", 1, 10, true, []string{}, "created_at")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Nil(t, whereSelectors)
|
||||||
|
require.NotNil(t, querySelectors)
|
||||||
|
|
||||||
|
for _, fnc := range whereSelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
for _, fnc := range querySelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM `users` ORDER BY `users`.`created_at` DESC", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
t.Run("PostgreSQL_NoPagination", func(t *testing.T) {
|
||||||
|
s := sql.Dialect(dialect.Postgres).Select("*").From(sql.Table("users"))
|
||||||
|
|
||||||
|
err, whereSelectors, querySelectors := BuildQuerySelector("", "", 1, 10, true, []string{}, "created_at")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Nil(t, whereSelectors)
|
||||||
|
require.NotNil(t, querySelectors)
|
||||||
|
|
||||||
|
for _, fnc := range whereSelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
for _, fnc := range querySelectors {
|
||||||
|
fnc(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
query, args := s.Query()
|
||||||
|
require.Equal(t, "SELECT * FROM \"users\" ORDER BY \"users\".\"created_at\" DESC", query)
|
||||||
|
require.Empty(t, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/go-kratos/kratos/v2/log"
|
"github.com/go-kratos/kratos/v2/log"
|
||||||
"github.com/oschwald/geoip2-golang"
|
"github.com/oschwald/geoip2-golang"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/geoip"
|
"github.com/tx7do/go-utils/geoip"
|
||||||
"github.com/tx7do/kratos-utils/geoip/geolite/assets"
|
"github.com/tx7do/go-utils/geoip/geolite/assets"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultOutputLanguage = "zh-CN"
|
const defaultOutputLanguage = "zh-CN"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module github.com/tx7do/kratos-utils/geoip
|
module github.com/tx7do/go-utils/geoip
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
@@ -17,3 +17,5 @@ require (
|
|||||||
golang.org/x/sys v0.10.0 // indirect
|
golang.org/x/sys v0.10.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/tx7do/go-utils => ../
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package qqwry
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/tx7do/kratos-utils/geoip"
|
"github.com/tx7do/go-utils/geoip"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/geoip/qqwry/assets"
|
"github.com/tx7do/go-utils/geoip/qqwry/assets"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
|||||||
36
gitautotag.sh
Normal file
36
gitautotag.sh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURTAG=`git describe --abbrev=0 --tags`;
|
||||||
|
CURTAG="${CURTAG/v/}"
|
||||||
|
|
||||||
|
IFS='.' read -a vers <<< "$CURTAG"
|
||||||
|
|
||||||
|
MAJ=${vers[0]}
|
||||||
|
MIN=${vers[1]}
|
||||||
|
BUG=${vers[2]}
|
||||||
|
echo "Current Tag: v$MAJ.$MIN.$BUG"
|
||||||
|
|
||||||
|
for cmd in "$@"
|
||||||
|
do
|
||||||
|
case $cmd in
|
||||||
|
"--major")
|
||||||
|
# $((MAJ+1))
|
||||||
|
((MAJ+=1))
|
||||||
|
MIN=0
|
||||||
|
BUG=0
|
||||||
|
echo "Incrementing Major Version#"
|
||||||
|
;;
|
||||||
|
"--minor")
|
||||||
|
((MIN+=1))
|
||||||
|
BUG=0
|
||||||
|
echo "Incrementing Minor Version#"
|
||||||
|
;;
|
||||||
|
"--bug")
|
||||||
|
((BUG+=1))
|
||||||
|
echo "Incrementing Bug Version#"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
NEWTAG="v$MAJ.$MIN.$BUG"
|
||||||
|
echo "Adding Tag: $NEWTAG";
|
||||||
|
git tag -a $NEWTAG -m $NEWTAG
|
||||||
5
go.mod
5
go.mod
@@ -1,8 +1,10 @@
|
|||||||
module github.com/tx7do/kratos-utils
|
module github.com/tx7do/go-utils
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/google/uuid v1.4.0
|
||||||
|
github.com/gosimple/slug v1.13.1
|
||||||
github.com/sony/sonyflake v1.2.0
|
github.com/sony/sonyflake v1.2.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
golang.org/x/crypto v0.14.0
|
golang.org/x/crypto v0.14.0
|
||||||
@@ -10,6 +12,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/gosimple/unidecode v1.0.1 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -1,6 +1,12 @@
|
|||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||||
|
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gosimple/slug v1.13.1 h1:bQ+kpX9Qa6tHRaK+fZR0A0M2Kd7Pa5eHPPsb1JpHD+Q=
|
||||||
|
github.com/gosimple/slug v1.13.1/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ=
|
||||||
|
github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o=
|
||||||
|
github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
|||||||
85
ioutil/path.go
Normal file
85
ioutil/path.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package ioutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetWorkingDirPath 获取工作路径
|
||||||
|
func GetWorkingDirPath() string {
|
||||||
|
dir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExePath 获取可执行程序路径
|
||||||
|
func GetExePath() string {
|
||||||
|
ex, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
exePath := filepath.Dir(ex)
|
||||||
|
return exePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAbsPath 获取绝对路径
|
||||||
|
func GetAbsPath() string {
|
||||||
|
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathExist 路径是否存在
|
||||||
|
func PathExist(path string) bool {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
if err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFileList 获取文件夹下面的所有文件的列表
|
||||||
|
func GetFileList(root string) []string {
|
||||||
|
var files []string
|
||||||
|
|
||||||
|
if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
files = append(files, path)
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFolderNameList 获取当前文件夹下面的所有文件夹名的列表
|
||||||
|
func GetFolderNameList(root string) []string {
|
||||||
|
var names []string
|
||||||
|
fs, _ := os.ReadDir(root)
|
||||||
|
for _, file := range fs {
|
||||||
|
if file.IsDir() {
|
||||||
|
names = append(names, file.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFile 读取文件
|
||||||
|
func ReadFile(path string) []byte {
|
||||||
|
content, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return content
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/trans"
|
"github.com/tx7do/go-utils/trans"
|
||||||
)
|
)
|
||||||
|
|
||||||
type idCounter uint32
|
type idCounter uint32
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/trans"
|
"github.com/tx7do/go-utils/trans"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenerateOrderIdWithRandom(t *testing.T) {
|
func TestGenerateOrderIdWithRandom(t *testing.T) {
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package pagination
|
package pagination
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultPage = 1 // 默认页数
|
||||||
|
DefaultPageSize = 10 // 默认每页行数
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetPageOffset 计算偏移量
|
||||||
func GetPageOffset(pageNum, pageSize int32) int {
|
func GetPageOffset(pageNum, pageSize int32) int {
|
||||||
return int((pageNum - 1) * pageSize)
|
return int((pageNum - 1) * pageSize)
|
||||||
}
|
}
|
||||||
|
|||||||
29
slug/slug.go
Normal file
29
slug/slug.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package slug
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gosimple/slug"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generate 生成短链接
|
||||||
|
func Generate(input string) string {
|
||||||
|
slug.Lowercase = true
|
||||||
|
return slug.MakeLang(input, "en")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateCaseSensitive 生成大小写敏感的短链接
|
||||||
|
func GenerateCaseSensitive(input string) string {
|
||||||
|
slug.Lowercase = false
|
||||||
|
return slug.MakeLang(input, "en")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateEnglish 生成英文短链接
|
||||||
|
func GenerateEnglish(input string) string {
|
||||||
|
slug.Lowercase = true
|
||||||
|
return slug.MakeLang(input, "en")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateGerman 生成德文短链接
|
||||||
|
func GenerateGerman(input string) string {
|
||||||
|
slug.Lowercase = true
|
||||||
|
return slug.MakeLang(input, "de")
|
||||||
|
}
|
||||||
88
slug/slug_test.go
Normal file
88
slug/slug_test.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package slug
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gosimple/slug"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGoSimple(t *testing.T) {
|
||||||
|
// 俄文
|
||||||
|
text := slug.Make("Hellö Wörld хелло ворлд")
|
||||||
|
assert.Equal(t, text, "hello-world-khello-vorld")
|
||||||
|
fmt.Println(text)
|
||||||
|
|
||||||
|
// 繁体中文
|
||||||
|
someText := slug.Make("影師")
|
||||||
|
assert.Equal(t, someText, "ying-shi")
|
||||||
|
fmt.Println(someText)
|
||||||
|
|
||||||
|
// 简体中文
|
||||||
|
cnText := slug.Make("天下太平")
|
||||||
|
assert.Equal(t, cnText, "tian-xia-tai-ping")
|
||||||
|
fmt.Println(cnText)
|
||||||
|
|
||||||
|
// 英文
|
||||||
|
enText := slug.MakeLang("This & that", "en")
|
||||||
|
assert.Equal(t, enText, "this-and-that")
|
||||||
|
fmt.Println(enText)
|
||||||
|
|
||||||
|
// 德文
|
||||||
|
deText := slug.MakeLang("Diese & Dass", "de")
|
||||||
|
assert.Equal(t, deText, "diese-und-dass")
|
||||||
|
fmt.Println(deText)
|
||||||
|
|
||||||
|
// 保持大小写
|
||||||
|
slug.Lowercase = false
|
||||||
|
deUppercaseText := slug.MakeLang("Diese & Dass", "de")
|
||||||
|
assert.Equal(t, deUppercaseText, "Diese-und-Dass")
|
||||||
|
fmt.Println(deUppercaseText)
|
||||||
|
|
||||||
|
// 字符替换
|
||||||
|
slug.CustomSub = map[string]string{
|
||||||
|
"water": "sand",
|
||||||
|
}
|
||||||
|
textSub := slug.Make("water is hot")
|
||||||
|
assert.Equal(t, textSub, "sand-is-hot")
|
||||||
|
fmt.Println(textSub)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerate(t *testing.T) {
|
||||||
|
// 俄文
|
||||||
|
text := Generate("Hellö Wörld хелло ворлд")
|
||||||
|
assert.Equal(t, text, "hello-world-khello-vorld")
|
||||||
|
fmt.Println(text)
|
||||||
|
|
||||||
|
// 繁体中文
|
||||||
|
someText := Generate("影師")
|
||||||
|
assert.Equal(t, someText, "ying-shi")
|
||||||
|
fmt.Println(someText)
|
||||||
|
|
||||||
|
// 简体中文
|
||||||
|
cnText := Generate("天下太平")
|
||||||
|
assert.Equal(t, cnText, "tian-xia-tai-ping")
|
||||||
|
fmt.Println(cnText)
|
||||||
|
|
||||||
|
// 英文
|
||||||
|
enText := GenerateEnglish("This & that")
|
||||||
|
assert.Equal(t, enText, "this-and-that")
|
||||||
|
fmt.Println(enText)
|
||||||
|
|
||||||
|
enText = GenerateCaseSensitive("This & That")
|
||||||
|
assert.Equal(t, enText, "This-and-That")
|
||||||
|
fmt.Println(enText)
|
||||||
|
|
||||||
|
// 德文
|
||||||
|
deText := GenerateGerman("Diese & Dass")
|
||||||
|
assert.Equal(t, deText, "diese-und-dass")
|
||||||
|
fmt.Println(deText)
|
||||||
|
|
||||||
|
slug.CustomSub = map[string]string{
|
||||||
|
"water": "sand",
|
||||||
|
}
|
||||||
|
textSub := Generate("water is hot")
|
||||||
|
assert.Equal(t, textSub, "sand-is-hot")
|
||||||
|
fmt.Println(textSub)
|
||||||
|
}
|
||||||
6
tag.bat
Normal file
6
tag.bat
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
git tag v1.1.4
|
||||||
|
git tag bank_card/v1.1.0
|
||||||
|
git tag entgo/v1.1.6
|
||||||
|
git tag geoip/v1.1.0
|
||||||
|
|
||||||
|
git push origin --tags
|
||||||
@@ -3,7 +3,7 @@ package util
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/trans"
|
"github.com/tx7do/go-utils/trans"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultTimeLocation *time.Location
|
var DefaultTimeLocation *time.Location
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tx7do/kratos-utils/trans"
|
"github.com/tx7do/go-utils/trans"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUnixMilliToStringPtr(t *testing.T) {
|
func TestUnixMilliToStringPtr(t *testing.T) {
|
||||||
|
|||||||
19
upgrade.bat
Normal file
19
upgrade.bat
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
echo off
|
||||||
|
|
||||||
|
::指定起始文件夹
|
||||||
|
set DIR="%cd%"
|
||||||
|
|
||||||
|
go get all
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
cd %DIR%/bank_card
|
||||||
|
go get all
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
cd %DIR%/entgo
|
||||||
|
go get all
|
||||||
|
go mod tidy
|
||||||
|
|
||||||
|
cd %DIR%/geoip
|
||||||
|
go get all
|
||||||
|
go mod tidy
|
||||||
7
uuid/test_trans.go
Normal file
7
uuid/test_trans.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package uuid
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestUUID(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
31
uuid/trans.go
Normal file
31
uuid/trans.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package uuid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/tx7do/go-utils/trans"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ToUuidPtr(str *string) *uuid.UUID {
|
||||||
|
var id *uuid.UUID
|
||||||
|
if str != nil {
|
||||||
|
_id, err := uuid.Parse(*str)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
id = &_id
|
||||||
|
}
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToUuid(str string) uuid.UUID {
|
||||||
|
id, _ := uuid.Parse(str)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToStringPtr(id *uuid.UUID) *string {
|
||||||
|
var strUUID *string
|
||||||
|
if id != nil {
|
||||||
|
strUUID = trans.String(id.String())
|
||||||
|
}
|
||||||
|
return strUUID
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user