Skip to content
This repository was archived by the owner on Sep 7, 2021. It is now read-only.
This repository is currently being migrated. It's locked while the migration is in progress.

Commit 98db3ef

Browse files
authored
improve sync2 (#1443)
1 parent c5ee68f commit 98db3ef

File tree

2 files changed

+139
-134
lines changed

2 files changed

+139
-134
lines changed

engine.go

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,32 @@ func (engine *Engine) NoAutoCondition(no ...bool) *Session {
377377
return session.NoAutoCondition(no...)
378378
}
379379

380+
func (engine *Engine) loadTableInfo(table *core.Table) error {
381+
colSeq, cols, err := engine.dialect.GetColumns(table.Name)
382+
if err != nil {
383+
return err
384+
}
385+
for _, name := range colSeq {
386+
table.AddColumn(cols[name])
387+
}
388+
indexes, err := engine.dialect.GetIndexes(table.Name)
389+
if err != nil {
390+
return err
391+
}
392+
table.Indexes = indexes
393+
394+
for _, index := range indexes {
395+
for _, name := range index.Cols {
396+
if col := table.GetColumn(name); col != nil {
397+
col.Indexes[index.Name] = index.Type
398+
} else {
399+
return fmt.Errorf("Unknown col %s in index %v of table %v, columns %v", name, index.Name, table.Name, table.ColumnsSeq())
400+
}
401+
}
402+
}
403+
return nil
404+
}
405+
380406
// DBMetas Retrieve all tables, columns, indexes' informations from database.
381407
func (engine *Engine) DBMetas() ([]*core.Table, error) {
382408
tables, err := engine.dialect.GetTables()
@@ -385,28 +411,9 @@ func (engine *Engine) DBMetas() ([]*core.Table, error) {
385411
}
386412

387413
for _, table := range tables {
388-
colSeq, cols, err := engine.dialect.GetColumns(table.Name)
389-
if err != nil {
390-
return nil, err
391-
}
392-
for _, name := range colSeq {
393-
table.AddColumn(cols[name])
394-
}
395-
indexes, err := engine.dialect.GetIndexes(table.Name)
396-
if err != nil {
414+
if err = engine.loadTableInfo(table); err != nil {
397415
return nil, err
398416
}
399-
table.Indexes = indexes
400-
401-
for _, index := range indexes {
402-
for _, name := range index.Cols {
403-
if col := table.GetColumn(name); col != nil {
404-
col.Indexes[index.Name] = index.Type
405-
} else {
406-
return nil, fmt.Errorf("Unknown col %s in index %v of table %v, columns %v", name, index.Name, table.Name, table.ColumnsSeq())
407-
}
408-
}
409-
}
410417
}
411418
return tables, nil
412419
}

session_schema.go

Lines changed: 112 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
228228
defer session.Close()
229229
}
230230

231-
tables, err := engine.DBMetas()
231+
tables, err := engine.dialect.GetTables()
232232
if err != nil {
233233
return err
234234
}
@@ -239,15 +239,12 @@ func (session *Session) Sync2(beans ...interface{}) error {
239239
session.resetStatement()
240240
}()
241241

242-
var structTables []*core.Table
243-
244242
for _, bean := range beans {
245243
v := rValue(bean)
246244
table, err := engine.mapType(v)
247245
if err != nil {
248246
return err
249247
}
250-
structTables = append(structTables, table)
251248
tbName := engine.TableName(bean)
252249
tbNameWithSchema := engine.TableName(tbName, true)
253250

@@ -259,6 +256,7 @@ func (session *Session) Sync2(beans ...interface{}) error {
259256
}
260257
}
261258

259+
// this is a new table
262260
if oriTable == nil {
263261
err = session.StoreEngine(session.statement.StoreEngine).createTable(bean)
264262
if err != nil {
@@ -274,148 +272,148 @@ func (session *Session) Sync2(beans ...interface{}) error {
274272
if err != nil {
275273
return err
276274
}
277-
} else {
278-
for _, col := range table.Columns() {
279-
var oriCol *core.Column
280-
for _, col2 := range oriTable.Columns() {
281-
if strings.EqualFold(col.Name, col2.Name) {
282-
oriCol = col2
283-
break
284-
}
285-
}
275+
continue
276+
}
286277

287-
if oriCol != nil {
288-
expectedType := engine.dialect.SqlType(col)
289-
curType := engine.dialect.SqlType(oriCol)
290-
if expectedType != curType {
291-
if expectedType == core.Text &&
292-
strings.HasPrefix(curType, core.Varchar) {
293-
// currently only support mysql & postgres
294-
if engine.dialect.DBType() == core.MYSQL ||
295-
engine.dialect.DBType() == core.POSTGRES {
296-
engine.logger.Infof("Table %s column %s change type from %s to %s\n",
297-
tbNameWithSchema, col.Name, curType, expectedType)
298-
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
299-
} else {
300-
engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s\n",
301-
tbNameWithSchema, col.Name, curType, expectedType)
302-
}
303-
} else if strings.HasPrefix(curType, core.Varchar) && strings.HasPrefix(expectedType, core.Varchar) {
304-
if engine.dialect.DBType() == core.MYSQL {
305-
if oriCol.Length < col.Length {
306-
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
307-
tbNameWithSchema, col.Name, oriCol.Length, col.Length)
308-
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
309-
}
310-
}
311-
} else {
312-
if !(strings.HasPrefix(curType, expectedType) && curType[len(expectedType)] == '(') {
313-
engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s",
314-
tbNameWithSchema, col.Name, curType, expectedType)
315-
}
316-
}
317-
} else if expectedType == core.Varchar {
318-
if engine.dialect.DBType() == core.MYSQL {
319-
if oriCol.Length < col.Length {
320-
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
321-
tbNameWithSchema, col.Name, oriCol.Length, col.Length)
322-
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
323-
}
324-
}
325-
}
326-
if col.Default != oriCol.Default {
327-
engine.logger.Warnf("Table %s Column %s db default is %s, struct default is %s",
328-
tbName, col.Name, oriCol.Default, col.Default)
329-
}
330-
if col.Nullable != oriCol.Nullable {
331-
engine.logger.Warnf("Table %s Column %s db nullable is %v, struct nullable is %v",
332-
tbName, col.Name, oriCol.Nullable, col.Nullable)
333-
}
334-
} else {
335-
session.statement.RefTable = table
336-
session.statement.tableName = tbNameWithSchema
337-
err = session.addColumn(col.Name)
278+
// this will modify an old table
279+
if err = engine.loadTableInfo(oriTable); err != nil {
280+
return err
281+
}
282+
283+
// check columns
284+
for _, col := range table.Columns() {
285+
var oriCol *core.Column
286+
for _, col2 := range oriTable.Columns() {
287+
if strings.EqualFold(col.Name, col2.Name) {
288+
oriCol = col2
289+
break
338290
}
339-
if err != nil {
291+
}
292+
293+
// column is not exist on table
294+
if oriCol == nil {
295+
session.statement.RefTable = table
296+
session.statement.tableName = tbNameWithSchema
297+
if err = session.addColumn(col.Name); err != nil {
340298
return err
341299
}
300+
continue
342301
}
343302

344-
var foundIndexNames = make(map[string]bool)
345-
var addedNames = make(map[string]*core.Index)
346-
347-
for name, index := range table.Indexes {
348-
var oriIndex *core.Index
349-
for name2, index2 := range oriTable.Indexes {
350-
if index.Equal(index2) {
351-
oriIndex = index2
352-
foundIndexNames[name2] = true
353-
break
303+
err = nil
304+
expectedType := engine.dialect.SqlType(col)
305+
curType := engine.dialect.SqlType(oriCol)
306+
if expectedType != curType {
307+
if expectedType == core.Text &&
308+
strings.HasPrefix(curType, core.Varchar) {
309+
// currently only support mysql & postgres
310+
if engine.dialect.DBType() == core.MYSQL ||
311+
engine.dialect.DBType() == core.POSTGRES {
312+
engine.logger.Infof("Table %s column %s change type from %s to %s\n",
313+
tbNameWithSchema, col.Name, curType, expectedType)
314+
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
315+
} else {
316+
engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s\n",
317+
tbNameWithSchema, col.Name, curType, expectedType)
354318
}
355-
}
356-
357-
if oriIndex != nil {
358-
if oriIndex.Type != index.Type {
359-
sql := engine.dialect.DropIndexSql(tbNameWithSchema, oriIndex)
360-
_, err = session.exec(sql)
361-
if err != nil {
362-
return err
319+
} else if strings.HasPrefix(curType, core.Varchar) && strings.HasPrefix(expectedType, core.Varchar) {
320+
if engine.dialect.DBType() == core.MYSQL {
321+
if oriCol.Length < col.Length {
322+
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
323+
tbNameWithSchema, col.Name, oriCol.Length, col.Length)
324+
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
363325
}
364-
oriIndex = nil
326+
}
327+
} else {
328+
if !(strings.HasPrefix(curType, expectedType) && curType[len(expectedType)] == '(') {
329+
engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s",
330+
tbNameWithSchema, col.Name, curType, expectedType)
365331
}
366332
}
367-
368-
if oriIndex == nil {
369-
addedNames[name] = index
333+
} else if expectedType == core.Varchar {
334+
if engine.dialect.DBType() == core.MYSQL {
335+
if oriCol.Length < col.Length {
336+
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
337+
tbNameWithSchema, col.Name, oriCol.Length, col.Length)
338+
_, err = session.exec(engine.dialect.ModifyColumnSql(tbNameWithSchema, col))
339+
}
370340
}
371341
}
342+
if col.Default != oriCol.Default {
343+
engine.logger.Warnf("Table %s Column %s db default is %s, struct default is %s",
344+
tbName, col.Name, oriCol.Default, col.Default)
345+
}
346+
if col.Nullable != oriCol.Nullable {
347+
engine.logger.Warnf("Table %s Column %s db nullable is %v, struct nullable is %v",
348+
tbName, col.Name, oriCol.Nullable, col.Nullable)
349+
}
350+
351+
if err != nil {
352+
return err
353+
}
354+
}
355+
356+
var foundIndexNames = make(map[string]bool)
357+
var addedNames = make(map[string]*core.Index)
372358

359+
for name, index := range table.Indexes {
360+
var oriIndex *core.Index
373361
for name2, index2 := range oriTable.Indexes {
374-
if _, ok := foundIndexNames[name2]; !ok {
375-
sql := engine.dialect.DropIndexSql(tbNameWithSchema, index2)
362+
if index.Equal(index2) {
363+
oriIndex = index2
364+
foundIndexNames[name2] = true
365+
break
366+
}
367+
}
368+
369+
if oriIndex != nil {
370+
if oriIndex.Type != index.Type {
371+
sql := engine.dialect.DropIndexSql(tbNameWithSchema, oriIndex)
376372
_, err = session.exec(sql)
377373
if err != nil {
378374
return err
379375
}
376+
oriIndex = nil
380377
}
381378
}
382379

383-
for name, index := range addedNames {
384-
if index.Type == core.UniqueType {
385-
session.statement.RefTable = table
386-
session.statement.tableName = tbNameWithSchema
387-
err = session.addUnique(tbNameWithSchema, name)
388-
} else if index.Type == core.IndexType {
389-
session.statement.RefTable = table
390-
session.statement.tableName = tbNameWithSchema
391-
err = session.addIndex(tbNameWithSchema, name)
392-
}
380+
if oriIndex == nil {
381+
addedNames[name] = index
382+
}
383+
}
384+
385+
for name2, index2 := range oriTable.Indexes {
386+
if _, ok := foundIndexNames[name2]; !ok {
387+
sql := engine.dialect.DropIndexSql(tbNameWithSchema, index2)
388+
_, err = session.exec(sql)
393389
if err != nil {
394390
return err
395391
}
396392
}
397393
}
398-
}
399394

400-
for _, table := range tables {
401-
var oriTable *core.Table
402-
for _, structTable := range structTables {
403-
if strings.EqualFold(table.Name, session.tbNameNoSchema(structTable)) {
404-
oriTable = structTable
405-
break
395+
for name, index := range addedNames {
396+
if index.Type == core.UniqueType {
397+
session.statement.RefTable = table
398+
session.statement.tableName = tbNameWithSchema
399+
err = session.addUnique(tbNameWithSchema, name)
400+
} else if index.Type == core.IndexType {
401+
session.statement.RefTable = table
402+
session.statement.tableName = tbNameWithSchema
403+
err = session.addIndex(tbNameWithSchema, name)
404+
}
405+
if err != nil {
406+
return err
406407
}
407408
}
408409

409-
if oriTable == nil {
410-
//engine.LogWarnf("Table %s has no struct to mapping it", table.Name)
411-
continue
412-
}
413-
414-
for _, colName := range table.ColumnsSeq() {
415-
if oriTable.GetColumn(colName) == nil {
416-
engine.logger.Warnf("Table %s has column %s but struct has not related field", engine.TableName(table.Name, true), colName)
410+
// check all the columns which removed from struct fields but left on database tables.
411+
for _, colName := range oriTable.ColumnsSeq() {
412+
if table.GetColumn(colName) == nil {
413+
engine.logger.Warnf("Table %s has column %s but struct has not related field", engine.TableName(oriTable.Name, true), colName)
417414
}
418415
}
419416
}
417+
420418
return nil
421419
}

0 commit comments

Comments
 (0)