@@ -13,6 +13,7 @@ import (
13
13
"os"
14
14
"path"
15
15
"path/filepath"
16
+ "regexp"
16
17
"strings"
17
18
"time"
18
19
@@ -284,11 +285,98 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
284
285
if tableName == "" || len (columnNames ) == 0 {
285
286
return nil
286
287
}
288
+ // TODO: This will not work if there are foreign keys
287
289
288
290
switch {
289
291
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
292
380
cols := ""
293
381
for _ , col := range columnNames {
294
382
if cols != "" {
0 commit comments