[#7689] fixed indexes update collection error
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/tools/dbutils"
|
||||
)
|
||||
|
||||
// see https://github.com/pocketbase/pocketbase/issues/7689
|
||||
func init() {
|
||||
core.SystemMigrations.Register(func(txApp core.App) error {
|
||||
collections, err := txApp.FindAllCollections()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, collection := range collections {
|
||||
// existing system collection indexes can't be modified and view don't have indexes
|
||||
if collection.System || collection.IsView() {
|
||||
continue
|
||||
}
|
||||
|
||||
masterIndexes := []struct {
|
||||
Name string `db:"name"`
|
||||
SQL string `db:"sql"`
|
||||
}{}
|
||||
|
||||
err := txApp.DB().Select("name", "sql").
|
||||
From("sqlite_master").
|
||||
AndWhere(dbx.HashExp{
|
||||
"type": "index",
|
||||
"tbl_name": collection.Name,
|
||||
}).
|
||||
AndWhere(dbx.NewExp("sql IS NOT NULL AND name NOT LIKE 'sqlite_autoindex_%'")).
|
||||
All(&masterIndexes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// no indexes
|
||||
if len(masterIndexes) == 0 && len(collection.Indexes) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
missingParsedIndexes := map[string]dbutils.Index{}
|
||||
|
||||
// find missing master indexes
|
||||
masterLoop:
|
||||
for _, masterIndex := range masterIndexes {
|
||||
mParsed := dbutils.ParseIndex(masterIndex.SQL)
|
||||
mParsed.SchemaName = ""
|
||||
mParsed.TableName = collection.Name
|
||||
|
||||
for _, raw := range collection.Indexes {
|
||||
cParsed := dbutils.ParseIndex(raw)
|
||||
|
||||
// index already exists (if needed it will be normalized on resave)
|
||||
if strings.EqualFold(cParsed.IndexName, mParsed.IndexName) {
|
||||
continue masterLoop
|
||||
}
|
||||
}
|
||||
|
||||
missingParsedIndexes[masterIndex.Name] = mParsed
|
||||
}
|
||||
|
||||
missingIndexesLoop:
|
||||
for _, missing := range missingParsedIndexes {
|
||||
missingSQL := missing.Build()
|
||||
|
||||
// drop the missing index to recreate later
|
||||
_, err := txApp.DB().DropIndex(missing.TableName, missing.IndexName).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to drop index %s: %w", missing.IndexName, err)
|
||||
}
|
||||
|
||||
// no recreate: duplicated single unique tokenKey or email
|
||||
// (auth collections are guaranteed to have them)
|
||||
if collection.IsAuth() && missing.Unique && len(missing.Columns) == 1 &&
|
||||
(strings.EqualFold(missing.Columns[0].Name, core.FieldNameTokenKey) || strings.EqualFold(missing.Columns[0].Name, core.FieldNameEmail)) {
|
||||
continue missingIndexesLoop
|
||||
}
|
||||
|
||||
// no recreate: the same index definition alreay exists
|
||||
// in the collection but with different name
|
||||
for _, raw := range collection.Indexes {
|
||||
cParsed := dbutils.ParseIndex(raw)
|
||||
cParsed.IndexName = missing.IndexName
|
||||
cParsed.SchemaName = missing.SchemaName
|
||||
cParsed.TableName = missing.TableName
|
||||
cSQL := cParsed.Build()
|
||||
|
||||
if missingSQL == cSQL {
|
||||
continue missingIndexesLoop
|
||||
}
|
||||
}
|
||||
|
||||
// recreate: add the missing index to the collection list and
|
||||
// leave the user to decide whether they want to keep it or not
|
||||
// (the index could have been previously created externally, e.g. via the sqlite3 cli)
|
||||
collection.Indexes = append(collection.Indexes, missingSQL)
|
||||
}
|
||||
|
||||
// resave to trigger indexes normalization
|
||||
err = txApp.Save(collection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user