minor internal indexes handling adjustments and test
This commit is contained in:
117
migrations/1679986800_add_indexes_column.go
Normal file
117
migrations/1679986800_add_indexes_column.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/tools/dbutils"
|
||||
"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 {
|
||||
c.Indexes = nil // reset
|
||||
|
||||
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 with 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
|
||||
FieldsLoop:
|
||||
for _, f := range c.Schema.Fields() {
|
||||
if !f.Unique {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, idx := range indexesByTableName[c.Name] {
|
||||
parsed := dbutils.ParseIndex(idx.Sql)
|
||||
if parsed.Unique && len(parsed.Columns) == 1 && strings.EqualFold(parsed.Columns[0].Name, f.Name) {
|
||||
continue FieldsLoop // already added
|
||||
}
|
||||
}
|
||||
|
||||
c.Indexes = append(c.Indexes, fmt.Sprintf(
|
||||
`CREATE UNIQUE INDEX "idx_unique_%s" on "%s" ("%s")`,
|
||||
f.Id,
|
||||
c.Name,
|
||||
f.Name,
|
||||
))
|
||||
}
|
||||
|
||||
if len(c.Indexes) > 0 {
|
||||
if err := dao.SaveCollection(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func(db dbx.Builder) error {
|
||||
_, err := db.DropColumn("_collections", "indexes").Execute()
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user