make dropTableColumns drop columns on sqlite and constraints on all (#6849)
This commit is contained in:
		
							parent
							
								
									5f25558ac2
								
							
						
					
					
						commit
						9fdd199cca
					
				
					 1 changed files with 90 additions and 2 deletions
				
			
		|  | @ -13,6 +13,7 @@ import ( | |||
| 	"os" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
|  | @ -284,11 +285,98 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin | |||
| 	if tableName == "" || len(columnNames) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	// TODO: This will not work if there are foreign keys
 | ||||
| 
 | ||||
| 	switch { | ||||
| 	case setting.UseSQLite3: | ||||
| 		log.Warn("Unable to drop columns in SQLite") | ||||
| 	case setting.UseMySQL, setting.UseTiDB, setting.UsePostgreSQL: | ||||
| 		// First drop the indexes on the columns
 | ||||
| 		res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName)) | ||||
| 		if errIndex != nil { | ||||
| 			return errIndex | ||||
| 		} | ||||
| 		for _, row := range res { | ||||
| 			indexName := row["name"] | ||||
| 			indexRes, err := sess.Query(fmt.Sprintf("PRAGMA index_info(`%s`)", indexName)) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			if len(indexRes) != 1 { | ||||
| 				continue | ||||
| 			} | ||||
| 			indexColumn := string(indexRes[0]["name"]) | ||||
| 			for _, name := range columnNames { | ||||
| 				if name == indexColumn { | ||||
| 					_, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s`", indexName)) | ||||
| 					if err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Here we need to get the columns from the original table
 | ||||
| 		sql := fmt.Sprintf("SELECT sql FROM sqlite_master WHERE tbl_name='%s' and type='table'", tableName) | ||||
| 		res, err := sess.Query(sql) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		tableSQL := string(res[0]["sql"]) | ||||
| 		tableSQL = tableSQL[strings.Index(tableSQL, "("):] | ||||
| 		for _, name := range columnNames { | ||||
| 			tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*[,)]").ReplaceAllString(tableSQL, "") | ||||
| 		} | ||||
| 
 | ||||
| 		columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1) | ||||
| 
 | ||||
| 		tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL | ||||
| 		if _, err := sess.Exec(tableSQL); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		// Now restore the data
 | ||||
| 		columnsSeparated := strings.Join(columns, ",") | ||||
| 		insertSQL := fmt.Sprintf("INSERT INTO `new_%s_new` (%s) SELECT %s FROM %s", tableName, columnsSeparated, columnsSeparated, tableName) | ||||
| 		if _, err := sess.Exec(insertSQL); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		// Now drop the old table
 | ||||
| 		if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		// Rename the table
 | ||||
| 		if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `new_%s_new` RENAME TO `%s`", tableName, tableName)); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 	case setting.UsePostgreSQL: | ||||
| 		cols := "" | ||||
| 		for _, col := range columnNames { | ||||
| 			if cols != "" { | ||||
| 				cols += ", " | ||||
| 			} | ||||
| 			cols += "DROP COLUMN `" + col + "` CASCADE" | ||||
| 		} | ||||
| 		if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { | ||||
| 			return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) | ||||
| 		} | ||||
| 	case setting.UseMySQL, setting.UseTiDB: | ||||
| 		// Drop indexes on columns first
 | ||||
| 		sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','")) | ||||
| 		res, err := sess.Query(sql) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		for _, index := range res { | ||||
| 			indexName := index["column_name"] | ||||
| 			_, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s` ON `%s`", indexName, tableName)) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// Now drop the columns
 | ||||
| 		cols := "" | ||||
| 		for _, col := range columnNames { | ||||
| 			if cols != "" { | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue