224 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package orm
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| type dbIndex struct {
 | |
| 	Table string
 | |
| 	Name  string
 | |
| 	Sql   string
 | |
| }
 | |
| 
 | |
| // create database drop sql.
 | |
| func getDbDropSql(al *alias) (sqls []string) {
 | |
| 	if len(modelCache.cache) == 0 {
 | |
| 		fmt.Println("no Model found, need register your model")
 | |
| 		os.Exit(2)
 | |
| 	}
 | |
| 
 | |
| 	Q := al.DbBaser.TableQuote()
 | |
| 
 | |
| 	for _, mi := range modelCache.allOrdered() {
 | |
| 		sqls = append(sqls, fmt.Sprintf(`DROP TABLE IF EXISTS %s%s%s`, Q, mi.table, Q))
 | |
| 	}
 | |
| 	return sqls
 | |
| }
 | |
| 
 | |
| // get database column type string.
 | |
| func getColumnTyp(al *alias, fi *fieldInfo) (col string) {
 | |
| 	T := al.DbBaser.DbTypes()
 | |
| 	fieldType := fi.fieldType
 | |
| 
 | |
| checkColumn:
 | |
| 	switch fieldType {
 | |
| 	case TypeBooleanField:
 | |
| 		col = T["bool"]
 | |
| 	case TypeCharField:
 | |
| 		col = fmt.Sprintf(T["string"], fi.size)
 | |
| 	case TypeTextField:
 | |
| 		col = T["string-text"]
 | |
| 	case TypeDateField:
 | |
| 		col = T["time.Time-date"]
 | |
| 	case TypeDateTimeField:
 | |
| 		col = T["time.Time"]
 | |
| 	case TypeBitField:
 | |
| 		col = T["int8"]
 | |
| 	case TypeSmallIntegerField:
 | |
| 		col = T["int16"]
 | |
| 	case TypeIntegerField:
 | |
| 		col = T["int32"]
 | |
| 	case TypeBigIntegerField:
 | |
| 		if al.Driver == DR_Sqlite {
 | |
| 			fieldType = TypeIntegerField
 | |
| 			goto checkColumn
 | |
| 		}
 | |
| 		col = T["int64"]
 | |
| 	case TypePositiveBitField:
 | |
| 		col = T["uint8"]
 | |
| 	case TypePositiveSmallIntegerField:
 | |
| 		col = T["uint16"]
 | |
| 	case TypePositiveIntegerField:
 | |
| 		col = T["uint32"]
 | |
| 	case TypePositiveBigIntegerField:
 | |
| 		col = T["uint64"]
 | |
| 	case TypeFloatField:
 | |
| 		col = T["float64"]
 | |
| 	case TypeDecimalField:
 | |
| 		s := T["float64-decimal"]
 | |
| 		if strings.Index(s, "%d") == -1 {
 | |
| 			col = s
 | |
| 		} else {
 | |
| 			col = fmt.Sprintf(s, fi.digits, fi.decimals)
 | |
| 		}
 | |
| 	case RelForeignKey, RelOneToOne:
 | |
| 		fieldType = fi.relModelInfo.fields.pk.fieldType
 | |
| 		goto checkColumn
 | |
| 	}
 | |
| 
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // create alter sql string.
 | |
| func getColumnAddQuery(al *alias, fi *fieldInfo) string {
 | |
| 	Q := al.DbBaser.TableQuote()
 | |
| 	typ := getColumnTyp(al, fi)
 | |
| 
 | |
| 	if fi.null == false {
 | |
| 		typ += " " + "NOT NULL"
 | |
| 	}
 | |
| 
 | |
| 	return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s", Q, fi.mi.table, Q, Q, fi.column, Q, typ)
 | |
| }
 | |
| 
 | |
| // create database creation string.
 | |
| func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex) {
 | |
| 	if len(modelCache.cache) == 0 {
 | |
| 		fmt.Println("no Model found, need register your model")
 | |
| 		os.Exit(2)
 | |
| 	}
 | |
| 
 | |
| 	Q := al.DbBaser.TableQuote()
 | |
| 	T := al.DbBaser.DbTypes()
 | |
| 	sep := fmt.Sprintf("%s, %s", Q, Q)
 | |
| 
 | |
| 	tableIndexes = make(map[string][]dbIndex)
 | |
| 
 | |
| 	for _, mi := range modelCache.allOrdered() {
 | |
| 		sql := fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
 | |
| 		sql += fmt.Sprintf("--  Table Structure for `%s`\n", mi.fullName)
 | |
| 		sql += fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
 | |
| 
 | |
| 		sql += fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s%s%s (\n", Q, mi.table, Q)
 | |
| 
 | |
| 		columns := make([]string, 0, len(mi.fields.fieldsDB))
 | |
| 
 | |
| 		sqlIndexes := [][]string{}
 | |
| 
 | |
| 		for _, fi := range mi.fields.fieldsDB {
 | |
| 
 | |
| 			column := fmt.Sprintf("    %s%s%s ", Q, fi.column, Q)
 | |
| 			col := getColumnTyp(al, fi)
 | |
| 
 | |
| 			if fi.auto {
 | |
| 				switch al.Driver {
 | |
| 				case DR_Sqlite, DR_Postgres:
 | |
| 					column += T["auto"]
 | |
| 				default:
 | |
| 					column += col + " " + T["auto"]
 | |
| 				}
 | |
| 			} else if fi.pk {
 | |
| 				column += col + " " + T["pk"]
 | |
| 			} else {
 | |
| 				column += col
 | |
| 
 | |
| 				if fi.null == false {
 | |
| 					column += " " + "NOT NULL"
 | |
| 				}
 | |
| 
 | |
| 				if fi.unique {
 | |
| 					column += " " + "UNIQUE"
 | |
| 				}
 | |
| 
 | |
| 				if fi.index {
 | |
| 					sqlIndexes = append(sqlIndexes, []string{fi.column})
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if strings.Index(column, "%COL%") != -1 {
 | |
| 				column = strings.Replace(column, "%COL%", fi.column, -1)
 | |
| 			}
 | |
| 
 | |
| 			columns = append(columns, column)
 | |
| 		}
 | |
| 
 | |
| 		if mi.model != nil {
 | |
| 			allnames := getTableUnique(mi.addrField)
 | |
| 			if !mi.manual && len(mi.uniques) > 0 {
 | |
| 				allnames = append(allnames, mi.uniques)
 | |
| 			}
 | |
| 			for _, names := range allnames {
 | |
| 				cols := make([]string, 0, len(names))
 | |
| 				for _, name := range names {
 | |
| 					if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol {
 | |
| 						cols = append(cols, fi.column)
 | |
| 					} else {
 | |
| 						panic(fmt.Errorf("cannot found column `%s` when parse UNIQUE in `%s.TableUnique`", name, mi.fullName))
 | |
| 					}
 | |
| 				}
 | |
| 				column := fmt.Sprintf("    UNIQUE (%s%s%s)", Q, strings.Join(cols, sep), Q)
 | |
| 				columns = append(columns, column)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		sql += strings.Join(columns, ",\n")
 | |
| 		sql += "\n)"
 | |
| 
 | |
| 		if al.Driver == DR_MySQL {
 | |
| 			var engine string
 | |
| 			if mi.model != nil {
 | |
| 				engine = getTableEngine(mi.addrField)
 | |
| 			}
 | |
| 			if engine == "" {
 | |
| 				engine = al.Engine
 | |
| 			}
 | |
| 			sql += " ENGINE=" + engine
 | |
| 		}
 | |
| 
 | |
| 		sql += ";"
 | |
| 		sqls = append(sqls, sql)
 | |
| 
 | |
| 		if mi.model != nil {
 | |
| 			for _, names := range getTableIndex(mi.addrField) {
 | |
| 				cols := make([]string, 0, len(names))
 | |
| 				for _, name := range names {
 | |
| 					if fi, ok := mi.fields.GetByAny(name); ok && fi.dbcol {
 | |
| 						cols = append(cols, fi.column)
 | |
| 					} else {
 | |
| 						panic(fmt.Errorf("cannot found column `%s` when parse INDEX in `%s.TableIndex`", name, mi.fullName))
 | |
| 					}
 | |
| 				}
 | |
| 				sqlIndexes = append(sqlIndexes, cols)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		for _, names := range sqlIndexes {
 | |
| 			name := mi.table + "_" + strings.Join(names, "_")
 | |
| 			cols := strings.Join(names, sep)
 | |
| 			sql := fmt.Sprintf("CREATE INDEX %s%s%s ON %s%s%s (%s%s%s);", Q, name, Q, Q, mi.table, Q, Q, cols, Q)
 | |
| 
 | |
| 			index := dbIndex{}
 | |
| 			index.Table = mi.table
 | |
| 			index.Name = name
 | |
| 			index.Sql = sql
 | |
| 
 | |
| 			tableIndexes[mi.table] = append(tableIndexes[mi.table], index)
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	return
 | |
| }
 |