Skip to content

Commit 9fdd199

Browse files
zeripathtechknowlogick
authored andcommitted
make dropTableColumns drop columns on sqlite and constraints on all (#6849)
1 parent 5f25558 commit 9fdd199

File tree

1 file changed

+90
-2
lines changed

1 file changed

+90
-2
lines changed

models/migrations/migrations.go

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"os"
1414
"path"
1515
"path/filepath"
16+
"regexp"
1617
"strings"
1718
"time"
1819

@@ -284,11 +285,98 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
284285
if tableName == "" || len(columnNames) == 0 {
285286
return nil
286287
}
288+
// TODO: This will not work if there are foreign keys
287289

288290
switch {
289291
case setting.UseSQLite3:
290-
log.Warn("Unable to drop columns in SQLite")
291-
case setting.UseMySQL, setting.UseTiDB, setting.UsePostgreSQL:
292+
// First drop the indexes on the columns
293+
res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName))
294+
if errIndex != nil {
295+
return errIndex
296+
}
297+
for _, row := range res {
298+
indexName := row["name"]
299+
indexRes, err := sess.Query(fmt.Sprintf("PRAGMA index_info(`%s`)", indexName))
300+
if err != nil {
301+
return err
302+
}
303+
if len(indexRes) != 1 {
304+
continue
305+
}
306+
indexColumn := string(indexRes[0]["name"])
307+
for _, name := range columnNames {
308+
if name == indexColumn {
309+
_, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s`", indexName))
310+
if err != nil {
311+
return err
312+
}
313+
}
314+
}
315+
}
316+
317+
// Here we need to get the columns from the original table
318+
sql := fmt.Sprintf("SELECT sql FROM sqlite_master WHERE tbl_name='%s' and type='table'", tableName)
319+
res, err := sess.Query(sql)
320+
if err != nil {
321+
return err
322+
}
323+
tableSQL := string(res[0]["sql"])
324+
tableSQL = tableSQL[strings.Index(tableSQL, "("):]
325+
for _, name := range columnNames {
326+
tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*[,)]").ReplaceAllString(tableSQL, "")
327+
}
328+
329+
columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1)
330+
331+
tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL
332+
if _, err := sess.Exec(tableSQL); err != nil {
333+
return err
334+
}
335+
336+
// Now restore the data
337+
columnsSeparated := strings.Join(columns, ",")
338+
insertSQL := fmt.Sprintf("INSERT INTO `new_%s_new` (%s) SELECT %s FROM %s", tableName, columnsSeparated, columnsSeparated, tableName)
339+
if _, err := sess.Exec(insertSQL); err != nil {
340+
return err
341+
}
342+
343+
// Now drop the old table
344+
if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil {
345+
return err
346+
}
347+
348+
// Rename the table
349+
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `new_%s_new` RENAME TO `%s`", tableName, tableName)); err != nil {
350+
return err
351+
}
352+
353+
case setting.UsePostgreSQL:
354+
cols := ""
355+
for _, col := range columnNames {
356+
if cols != "" {
357+
cols += ", "
358+
}
359+
cols += "DROP COLUMN `" + col + "` CASCADE"
360+
}
361+
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
362+
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
363+
}
364+
case setting.UseMySQL, setting.UseTiDB:
365+
// Drop indexes on columns first
366+
sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','"))
367+
res, err := sess.Query(sql)
368+
if err != nil {
369+
return err
370+
}
371+
for _, index := range res {
372+
indexName := index["column_name"]
373+
_, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s` ON `%s`", indexName, tableName))
374+
if err != nil {
375+
return err
376+
}
377+
}
378+
379+
// Now drop the columns
292380
cols := ""
293381
for _, col := range columnNames {
294382
if cols != "" {

0 commit comments

Comments
 (0)