feat: create index method

This commit is contained in:
Reinaldy Rafli 2021-11-09 12:16:10 +07:00
parent 8163afaf1b
commit 070280bdf7
No known key found for this signature in database
GPG Key ID: CFDB9400255D8CB6
5 changed files with 238 additions and 0 deletions

20
bob.go
View File

@ -40,6 +40,16 @@ func (b BobBuilderType) CreateTableIfNotExists(table string) CreateBuilder {
return CreateBuilder(b).name(table).ifNotExists()
}
// CreateIndex creates an index with CreateIndexBuilder interface.
func (b BobBuilderType) CreateIndex(name string) IndexBuilder {
return IndexBuilder(b).name(name)
}
// CreateIndexIfNotExists creates an index with CreateIndexBuilder interface, if the index doesn't exists.
func (b BobBuilderType) CreateIndexIfNotExists(name string) IndexBuilder {
return IndexBuilder(b).name(name).ifNotExists()
}
// HasTable checks if a table exists with HasBuilder interface
func (b BobBuilderType) HasTable(table string) HasBuilder {
return HasBuilder(b).HasTable(table)
@ -172,3 +182,13 @@ func Truncate(table string) TruncateBuilder {
func Upsert(table string, dialect int) UpsertBuilder {
return BobStmtBuilder.Upsert(table, dialect)
}
// CreateIndex creates an index with CreateIndexBuilder interface.
func CreateIndex(name string) IndexBuilder {
return BobStmtBuilder.CreateIndex(name)
}
// CreateIndexIfNotExists creates an index with CreateIndexBuilder interface, if the index doesn't exists.
func CreateIndexIfNotExists(name string) IndexBuilder {
return BobStmtBuilder.CreateIndexIfNotExists(name)
}

127
create_index.go Normal file
View File

@ -0,0 +1,127 @@
package bob
import (
"errors"
"strings"
"github.com/lann/builder"
)
type IndexBuilder builder.Builder
type indexData struct {
Unique bool
Spatial bool
Fulltext bool
Name string
TableName string
Columns []IndexColumn
IfNotExists bool
}
type IndexColumn struct {
Name string
Extras []string
Collate string
}
func init() {
builder.Register(IndexBuilder{}, indexData{})
}
func (i IndexBuilder) Unique() IndexBuilder {
return builder.Set(i, "Unique", true).(IndexBuilder)
}
func (i IndexBuilder) Spatial() IndexBuilder {
return builder.Set(i, "Spatial", true).(IndexBuilder)
}
func (i IndexBuilder) Fulltext() IndexBuilder {
return builder.Set(i, "Fulltext", true).(IndexBuilder)
}
func (i IndexBuilder) name(name string) IndexBuilder {
return builder.Set(i, "Name", name).(IndexBuilder)
}
func (i IndexBuilder) ifNotExists() IndexBuilder {
return builder.Set(i, "IfNotExists", true).(IndexBuilder)
}
func (i IndexBuilder) On(table string) IndexBuilder {
return builder.Set(i, "TableName", table).(IndexBuilder)
}
func (i IndexBuilder) Columns(column IndexColumn) IndexBuilder {
return builder.Append(i, "Columns", column).(IndexBuilder)
}
func (i IndexBuilder) ToSql() (string, []interface{}, error) {
data := builder.GetStruct(i).(indexData)
return data.ToSql()
}
func (i *indexData) ToSql() (sqlStr string, args []interface{}, err error) {
if i.Name == "" {
err = errors.New("index name is required on create index statement")
return
}
if i.TableName == "" {
err = errors.New("a table name must be specified on create index statement")
return
}
if len(i.Columns) == 0 {
err = errors.New("should at least specify one column for create index statement")
return
}
var sql strings.Builder
sql.WriteString("CREATE ")
if i.Unique {
sql.WriteString("UNIQUE ")
}
if i.Fulltext {
sql.WriteString("FULLTEXT ")
}
if i.Spatial {
sql.WriteString("SPATIAL ")
}
sql.WriteString("INDEX ")
if i.IfNotExists {
sql.WriteString("IF NOT EXISTS ")
}
sql.WriteString(i.Name + " ")
sql.WriteString("ON ")
sql.WriteString(i.TableName + " ")
var columns []string
for _, column := range i.Columns {
var colBuilder strings.Builder
colBuilder.WriteString(column.Name)
if column.Collate != "" {
colBuilder.WriteString(" COLLATE " + column.Collate)
}
if len(column.Extras) > 0 {
colBuilder.WriteString(" " + strings.Join(column.Extras, " "))
}
columns = append(columns, colBuilder.String())
}
sql.WriteString("(")
sql.WriteString(strings.Join(columns, ", "))
sql.WriteString(");")
sqlStr = sql.String()
return
}

91
create_index_test.go Normal file
View File

@ -0,0 +1,91 @@
package bob_test
import (
"testing"
"github.com/aldy505/bob"
)
func TestCreateIndex(t *testing.T) {
sql, _, err := bob.
CreateIndexIfNotExists("email_idx").
On("users").
Unique().
Spatial().
Fulltext().
Columns(bob.IndexColumn{Name: "email"}).
ToSql()
if err != nil {
t.Fatal(err.Error())
}
result := "CREATE UNIQUE FULLTEXT SPATIAL INDEX IF NOT EXISTS email_idx ON users (email);"
if sql != result {
t.Fatal("sql is not equal to result:", sql)
}
}
func TestCreateIndex_Simple(t *testing.T) {
sql, _, err := bob.
CreateIndex("idx_email").
On("users").
Columns(bob.IndexColumn{Name: "email", Collate: "DEFAULT", Extras: []string{"ASC"}}).
Columns(bob.IndexColumn{Name: "name", Extras: []string{"DESC"}}).
ToSql()
if err != nil {
t.Fatal(err.Error())
}
result := "CREATE INDEX idx_email ON users (email COLLATE DEFAULT ASC, name DESC);"
if sql != result {
t.Fatal("sql is not equal to result:", sql)
}
}
func TestCreateIndex_Error(t *testing.T) {
t.Run("without index", func(t *testing.T) {
_, _, err := bob.
CreateIndex("").
On("users").
Columns(bob.IndexColumn{Name: "email", Collate: "DEFAULT", Extras: []string{"ASC"}}).
Columns(bob.IndexColumn{Name: "name", Extras: []string{"DESC"}}).
ToSql()
if err == nil {
t.Fatal("error is nil")
}
if err.Error() != "index name is required on create index statement" {
t.Fatal("error is not equal to result:", err.Error())
}
})
t.Run("without table name", func(t *testing.T) {
_, _, err := bob.
CreateIndex("name").
On("").
Columns(bob.IndexColumn{Name: "email", Collate: "DEFAULT", Extras: []string{"ASC"}}).
Columns(bob.IndexColumn{Name: "name", Extras: []string{"DESC"}}).
ToSql()
if err == nil {
t.Fatal("error is nil")
}
if err.Error() != "a table name must be specified on create index statement" {
t.Fatal("error is not equal to result:", err.Error())
}
})
t.Run("without columns", func(t *testing.T) {
_, _, err := bob.
CreateIndex("name").
On("users").
ToSql()
if err == nil {
t.Fatal("error is nil")
}
if err.Error() != "should at least specify one column for create index statement" {
t.Fatal("error is not equal to result:", err.Error())
}
})
}