8
8
9
9
"gorm.io/gorm"
10
10
"gorm.io/gorm/clause"
11
+ "gorm.io/gorm/logger"
11
12
"gorm.io/gorm/migrator"
12
13
"gorm.io/gorm/schema"
13
14
)
@@ -36,6 +37,58 @@ func (m Migrator) GetTables() (tableList []string, err error) {
36
37
return tableList , m .DB .Raw ("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG = ?" , m .CurrentDatabase ()).Scan (& tableList ).Error
37
38
}
38
39
40
+ func (m Migrator ) CreateTable (values ... interface {}) (err error ) {
41
+ if err = m .Migrator .CreateTable (values ... ); err != nil {
42
+ return
43
+ }
44
+ for _ , value := range m .ReorderModels (values , false ) {
45
+ if err = m .RunWithValue (value , func (stmt * gorm.Statement ) (err error ) {
46
+ if stmt .Schema == nil {
47
+ return
48
+ }
49
+ for _ , fieldName := range stmt .Schema .DBNames {
50
+ field := stmt .Schema .FieldsByDBName [fieldName ]
51
+ if field .Comment == "" {
52
+ continue
53
+ }
54
+ if err = m .setColumnComment (stmt , field , true ); err != nil {
55
+ return
56
+ }
57
+ }
58
+ return
59
+ }); err != nil {
60
+ return
61
+ }
62
+ }
63
+ return
64
+ }
65
+
66
+ func (m Migrator ) setColumnComment (stmt * gorm.Statement , field * schema.Field , add bool ) error {
67
+ schemaName := m .getTableSchemaName (stmt .Schema )
68
+ // add field comment
69
+ if add {
70
+ return m .DB .Exec (
71
+ "EXEC sp_addextendedproperty 'MS_Description', ?, 'SCHEMA', ?, 'TABLE', ?, 'COLUMN', ?" ,
72
+ field .Comment , schemaName , stmt .Table , field .DBName ,
73
+ ).Error
74
+ }
75
+ // update field comment
76
+ return m .DB .Exec (
77
+ "EXEC sp_updateextendedproperty 'MS_Description', ?, 'SCHEMA', ?, 'TABLE', ?, 'COLUMN', ?" ,
78
+ field .Comment , schemaName , stmt .Table , field .DBName ,
79
+ ).Error
80
+ }
81
+
82
+ func (m Migrator ) getTableSchemaName (schema * schema.Schema ) string {
83
+ // return the schema name if it is explicitly provided in the table name
84
+ // otherwise return default schema name
85
+ schemaName := getTableSchemaName (schema )
86
+ if schemaName == "" {
87
+ schemaName = m .DefaultSchema ()
88
+ }
89
+ return schemaName
90
+ }
91
+
39
92
func getTableSchemaName (schema * schema.Schema ) string {
40
93
// return the schema name if it is explicitly provided in the table name
41
94
// otherwise return a sql wildcard -> use any table_schema
@@ -141,6 +194,26 @@ func (m Migrator) RenameTable(oldName, newName interface{}) error {
141
194
).Error
142
195
}
143
196
197
+ func (m Migrator ) AddColumn (value interface {}, name string ) error {
198
+ if err := m .Migrator .AddColumn (value , name ); err != nil {
199
+ return err
200
+ }
201
+
202
+ return m .RunWithValue (value , func (stmt * gorm.Statement ) (err error ) {
203
+ if stmt .Schema != nil {
204
+ if field := stmt .Schema .LookUpField (name ); field != nil {
205
+ if field .Comment == "" {
206
+ return
207
+ }
208
+ if err = m .setColumnComment (stmt , field , true ); err != nil {
209
+ return
210
+ }
211
+ }
212
+ }
213
+ return
214
+ })
215
+ }
216
+
144
217
func (m Migrator ) HasColumn (value interface {}, field string ) bool {
145
218
var count int64
146
219
m .RunWithValue (value , func (stmt * gorm.Statement ) error {
@@ -200,6 +273,38 @@ func (m Migrator) RenameColumn(value interface{}, oldName, newName string) error
200
273
})
201
274
}
202
275
276
+ func (m Migrator ) GetColumnComment (stmt * gorm.Statement , fieldDBName string ) (description string ) {
277
+ queryTx := m .DB .Session (& gorm.Session {Logger : m .DB .Logger .LogMode (logger .Warn )})
278
+ if m .DB .DryRun {
279
+ queryTx .DryRun = false
280
+ }
281
+ var comment sql.NullString
282
+ queryTx .Raw ("SELECT value FROM ?.sys.fn_listextendedproperty('MS_Description', 'SCHEMA', ?, 'TABLE', ?, 'COLUMN', ?)" ,
283
+ gorm .Expr (m .CurrentDatabase ()), m .getTableSchemaName (stmt .Schema ), stmt .Table , fieldDBName ).Scan (& comment )
284
+ if comment .Valid {
285
+ description = comment .String
286
+ }
287
+ return
288
+ }
289
+
290
+ func (m Migrator ) MigrateColumn (value interface {}, field * schema.Field , columnType gorm.ColumnType ) error {
291
+ if err := m .Migrator .MigrateColumn (value , field , columnType ); err != nil {
292
+ return err
293
+ }
294
+
295
+ return m .RunWithValue (value , func (stmt * gorm.Statement ) (err error ) {
296
+ description := m .GetColumnComment (stmt , field .DBName )
297
+ if field .Comment != description {
298
+ if description == "" {
299
+ err = m .setColumnComment (stmt , field , true )
300
+ } else {
301
+ err = m .setColumnComment (stmt , field , false )
302
+ }
303
+ }
304
+ return
305
+ })
306
+ }
307
+
203
308
var defaultValueTrimRegexp = regexp .MustCompile ("^\\ ('?([^']*)'?\\ )$" )
204
309
205
310
// ColumnTypes return columnTypes []gorm.ColumnType and execErr error
@@ -215,9 +320,20 @@ func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) {
215
320
rows .Close ()
216
321
217
322
{
323
+ _ , schemaName , tableName := splitFullQualifiedName (stmt .Table )
324
+
325
+ query := "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_DEFAULT, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, DATETIME_PRECISION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = ? AND TABLE_NAME = ?"
326
+
327
+ queryParameters := []interface {}{m .CurrentDatabase (), tableName }
328
+
329
+ if schemaName != "" {
330
+ query += " AND TABLE_SCHEMA = ?"
331
+ queryParameters = append (queryParameters , schemaName )
332
+ }
333
+
218
334
var (
219
- columnTypeSQL = "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_DEFAULT, IS_NULLABLE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, DATETIME_PRECISION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = ? AND TABLE_NAME = ?"
220
- columns , rowErr = m .DB .Raw (columnTypeSQL , m . CurrentDatabase (), stmt . Table ).Rows ()
335
+ columnTypeSQL = query
336
+ columns , rowErr = m .DB .Raw (columnTypeSQL , queryParameters ... ).Rows ()
221
337
)
222
338
223
339
if rowErr != nil {
@@ -272,7 +388,17 @@ func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) {
272
388
}
273
389
274
390
{
275
- columnTypeRows , err := m .DB .Raw ("SELECT c.COLUMN_NAME, t.CONSTRAINT_TYPE FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE c ON c.CONSTRAINT_NAME=t.CONSTRAINT_NAME WHERE t.CONSTRAINT_TYPE IN ('PRIMARY KEY', 'UNIQUE') AND c.TABLE_CATALOG = ? AND c.TABLE_NAME = ?" , m .CurrentDatabase (), stmt .Table ).Rows ()
391
+ _ , schemaName , tableName := splitFullQualifiedName (stmt .Table )
392
+ query := "SELECT c.COLUMN_NAME, t.CONSTRAINT_TYPE FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS t JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE c ON c.CONSTRAINT_NAME=t.CONSTRAINT_NAME WHERE t.CONSTRAINT_TYPE IN ('PRIMARY KEY', 'UNIQUE') AND c.TABLE_CATALOG = ? AND c.TABLE_NAME = ?"
393
+
394
+ queryParameters := []interface {}{m .CurrentDatabase (), tableName }
395
+
396
+ if schemaName != "" {
397
+ query += " AND c.TABLE_SCHEMA = ?"
398
+ queryParameters = append (queryParameters , schemaName )
399
+ }
400
+
401
+ columnTypeRows , err := m .DB .Raw (query , queryParameters ... ).Rows ()
276
402
if err != nil {
277
403
return err
278
404
}
0 commit comments