Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dialect/entsql: add support for index-type annotation #2353

Merged
merged 2 commits into from
Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions dialect/entsql/annotation.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,30 @@ type IndexAnnotation struct {
// CREATE INDEX `table_c1_c2_c3` ON `table`(`c1` DESC, `c2` DESC, `c3`)
//
DescColumns map[string]bool

// Type defines the type of the index.
// In MySQL, the following annotation maps to:
//
// index.Fields("c1").
// Annotation(
// entsql.IndexType("FULLTEXT"),
// )
//
// CREATE FULLTEXT INDEX `table_c1` ON `table`(`c1`)
//
Type string

// Types is like the Type option but allows mapping an index-type per dialect.
//
// index.Fields("c1").
// Annotation(
// entsql.IndexTypes(map[string]string{
// dialect.MySQL: "FULLTEXT",
// dialect.Postgres: "GIN",
// }),
// )
//
Types map[string]string
}

// Prefix returns a new index annotation with a single string column index.
Expand Down Expand Up @@ -293,6 +317,34 @@ func DescColumns(names ...string) *IndexAnnotation {
return ant
}

// Type defines the type of the index.
// In MySQL, the following annotation maps to:
//
// index.Fields("c1").
// Annotation(
// entsql.IndexType("FULLTEXT"),
// )
//
// CREATE FULLTEXT INDEX `table_c1` ON `table`(`c1`)
//
func IndexType(t string) *IndexAnnotation {
return &IndexAnnotation{Type: t}
}

// Types is like the Type option but allows mapping an index-type per dialect.
//
// index.Fields("c1").
// Annotations(
// entsql.IndexTypes(map[string]string{
// dialect.MySQL: "FULLTEXT",
// dialect.Postgres: "GIN",
// }),
// )
//
func IndexTypes(types map[string]string) *IndexAnnotation {
return &IndexAnnotation{Types: types}
}

// Name describes the annotation name.
func (IndexAnnotation) Name() string {
return "EntSQLIndexes"
Expand Down Expand Up @@ -333,6 +385,12 @@ func (a IndexAnnotation) Merge(other schema.Annotation) schema.Annotation {
a.DescColumns[column] = desc
}
}
if ant.Type != "" {
a.Type = ant.Type
}
if ant.Types != nil {
a.Types = ant.Types
}
return a
}

Expand Down
17 changes: 17 additions & 0 deletions dialect/sql/schema/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -951,5 +951,22 @@ func (d *MySQL) atIndex(idx1 *Index, t2 *schema.Table, idx2 *schema.Index) error
}
idx2.AddParts(part)
}
if t, ok := indexType(idx1, dialect.MySQL); ok {
idx2.AddAttrs(&mysql.IndexType{T: t})
}
return nil
}

func indexType(idx *Index, d string) (string, bool) {
ant := idx.Annotation
if ant == nil {
return "", false
}
if ant.Types != nil && ant.Types[d] != "" {
a8m marked this conversation as resolved.
Show resolved Hide resolved
return ant.Types[d], true
}
if ant.Type != "" {
return ant.Type, true
}
return "", false
}
3 changes: 3 additions & 0 deletions dialect/sql/schema/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -779,5 +779,8 @@ func (d *Postgres) atIndex(idx1 *Index, t2 *schema.Table, idx2 *schema.Index) er
}
idx2.AddParts(&schema.IndexPart{C: c2})
}
if t, ok := indexType(idx1, dialect.Postgres); ok {
idx2.AddAttrs(&postgres.IndexType{T: t})
}
return nil
}
10 changes: 10 additions & 0 deletions entc/gen/template/migrate/schema.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ var (
{{- end }}
},
{{- end }}
{{- with $ant.Type }}
Type: "{{ . }}",
{{- end }}
{{- with $keys := keys $ant.Types }}
Types: map[string]string{
{{- range $k := $keys }}
"{{ $k }}": "{{ index $ant.Types $k }}",
{{- end }}
},
{{- end }}
},
{{- end }}
},
Expand Down
10 changes: 10 additions & 0 deletions entc/integration/migrate/entv2/migrate/schema.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions entc/integration/migrate/entv2/schema/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"entgo.io/ent"
"entgo.io/ent/dialect"
a8m marked this conversation as resolved.
Show resolved Hide resolved
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
Expand Down Expand Up @@ -126,6 +127,14 @@ func (User) Indexes() []ent.Index {
Unique(),
index.Fields("age").
Annotations(entsql.Desc()),
// Enable FULLTEXT search on "nickname"
// field only in MySQL.
index.Fields("nickname").
Annotations(
entsql.IndexTypes(map[string]string{
dialect.MySQL: "FULLTEXT",
}),
),
}
}

Expand Down
16 changes: 16 additions & 0 deletions entc/integration/migrate/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func TestMySQL(t *testing.T) {
if version == "8" {
CheckConstraint(t, clientv2)
}
NicknameSearch(t, clientv2)
})
}
}
Expand Down Expand Up @@ -347,6 +348,21 @@ func CheckConstraint(t *testing.T, client *entv2.Client) {
require.Error(t, err)
}

func NicknameSearch(t *testing.T, client *entv2.Client) {
ctx := context.Background()
names := client.User.Query().
Where(func(s *sql.Selector) {
s.Where(sql.P(func(b *sql.Builder) {
b.WriteString("MATCH(").Ident(user.FieldNickname).WriteString(") AGAINST(").Arg("nick_bar | nick_foo").WriteString(")")
}))
}).
Unique(true).
Order(entv2.Asc(user.FieldNickname)).
Select(user.FieldNickname).
StringsX(ctx)
require.Equal(t, []string{"nick_bar", "nick_foo"}, names)
}

func EqualFold(t *testing.T, client *entv2.Client) {
ctx := context.Background()
t.Log("testing equal-fold on sql specific dialects")
Expand Down