pocketbase/migrations/1678470811_add_indexes_colu...

107 lines
2.6 KiB
Go

package migrations
import (
"fmt"
"strings"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/tools/list"
)
// Adds _collections indexes column (if not already).
//
// Note: This migration will be deleted once schema.SchemaField.Unuique is removed.
func init() {
AppMigrations.Register(func(db dbx.Builder) error {
dao := daos.New(db)
cols, err := dao.GetTableColumns("_collections")
if err != nil {
return err
}
for _, col := range cols {
if col == "indexes" {
return nil // already existing (probably via the init migration)
}
}
if _, err := db.AddColumn("_collections", "indexes", `JSON DEFAULT "[]" NOT NULL`).Execute(); err != nil {
return err
}
collections := []*models.Collection{}
if err := dao.CollectionQuery().AndWhere(dbx.NewExp("type != 'view'")).All(&collections); err != nil {
return err
}
type indexInfo struct {
Sql string `db:"sql"`
IndexName string `db:"name"`
TableName string `db:"tbl_name"`
}
indexesQuery := db.NewQuery(`SELECT * FROM sqlite_master WHERE type = "index" and sql is not null`)
rawIndexes := []indexInfo{}
if err := indexesQuery.All(&rawIndexes); err != nil {
return err
}
indexesByTableName := map[string][]indexInfo{}
for _, idx := range rawIndexes {
indexesByTableName[idx.TableName] = append(indexesByTableName[idx.TableName], idx)
}
for _, c := range collections {
totalIndexesBefore := len(c.Indexes)
excludeIndexes := []string{
"_" + c.Id + "_email_idx",
"_" + c.Id + "_username_idx",
"_" + c.Id + "_tokenKey_idx",
}
// convert custom indexes into the related collections
for _, idx := range indexesByTableName[c.Name] {
if strings.Contains(idx.IndexName, "sqlite_autoindex_") ||
list.ExistInSlice(idx.IndexName, excludeIndexes) {
continue
}
// drop old index (it will be recreated witht the collection)
if _, err := db.DropIndex(idx.TableName, idx.IndexName).Execute(); err != nil {
return err
}
c.Indexes = append(c.Indexes, idx.Sql)
}
// convert unique fields to indexes
for _, f := range c.Schema.Fields() {
if f.Unique {
c.Indexes = append(c.Indexes, fmt.Sprintf(
`CREATE UNIQUE INDEX IF NOT EXISTS idx_%s on %s (%s)`,
f.Id,
c.Name,
f.Name,
))
}
}
if totalIndexesBefore != len(c.Indexes) {
if err := dao.SaveCollection(c); err != nil {
return err
}
}
}
return nil
}, func(db dbx.Builder) error {
_, err := db.DropColumn("_collections", "indexes").Execute()
return err
})
}