diff --git a/aorm.go b/aorm.go index 10fde4c..3268f5d 100644 --- a/aorm.go +++ b/aorm.go @@ -3,6 +3,8 @@ package aorm import ( "database/sql" //只需导入你需要的驱动即可 "github.com/tangpanqing/aorm/executor" + "github.com/tangpanqing/aorm/migrator" + "github.com/tangpanqing/aorm/model" ) // DbContent 数据库连接与数据库类型 @@ -11,6 +13,7 @@ type DbContent struct { DbLink *sql.DB } +//Open 开始一个数据库连接 func Open(driverName string, dataSourceName string) (DbContent, error) { db, err := sql.Open(driverName, dataSourceName) if err != nil { @@ -23,8 +26,8 @@ func Open(driverName string, dataSourceName string) (DbContent, error) { }, nil } -// Use 使用数据库连接,或者事务 -func Use(linkCommon executor.LinkCommon) *executor.Executor { +// Use 开始一个数据库操作 +func Use(linkCommon model.LinkCommon) *executor.Executor { executor := &executor.Executor{ LinkCommon: linkCommon, } @@ -32,20 +35,20 @@ func Use(linkCommon executor.LinkCommon) *executor.Executor { return executor } -func UseNew(dbContent DbContent) *executor.Executor { - executor := &executor.Executor{ - LinkCommon: dbContent.DbLink, - } - - return executor -} - // Sub 子查询 func Sub() *executor.Executor { executor := &executor.Executor{} return executor } +// Migrator 开始一个数据库迁移 +func Migrator(linkCommon model.LinkCommon) *migrator.Migrator { + mi := &migrator.Migrator{ + LinkCommon: linkCommon, + } + return mi +} + //清空查询条件,复用对象 //func (ex *executor.Executor) clear() { // ex.tableName = "" diff --git a/executor/crud.go b/executor/crud.go index 2bee28b..d6c58ba 100644 --- a/executor/crud.go +++ b/executor/crud.go @@ -4,7 +4,7 @@ import ( "database/sql" "errors" "fmt" - "github.com/tangpanqing/aorm" + "github.com/tangpanqing/aorm/helper" "github.com/tangpanqing/aorm/null" "reflect" "strings" @@ -60,7 +60,7 @@ func (ex *Executor) Insert(dest interface{}) (int64, error) { for i := 0; i < typeOf.Elem().NumField(); i++ { isNotNull := valueOf.Elem().Field(i).Field(0).Field(1).Bool() if isNotNull { - key := aorm.UnderLine(typeOf.Elem().Field(i).Name) + key := helper.UnderLine(typeOf.Elem().Field(i).Name) val := valueOf.Elem().Field(i).Field(0).Field(0).Interface() keys = append(keys, key) paramList = append(paramList, val) @@ -108,7 +108,7 @@ func (ex *Executor) InsertBatch(values interface{}) (int64, error) { isNotNull := valueOf.Index(j).Field(i).Field(0).Field(1).Bool() if isNotNull { if j == 0 { - key := aorm.UnderLine(typeOf.Field(i).Name) + key := helper.UnderLine(typeOf.Field(i).Name) keys = append(keys, key) } @@ -561,7 +561,7 @@ func (ex *Executor) Where(dest interface{}) *Executor { for i := 0; i < typeOf.Elem().NumField(); i++ { isNotNull := valueOf.Elem().Field(i).Field(0).Field(1).Bool() if isNotNull { - key := aorm.UnderLine(typeOf.Elem().Field(i).Name) + key := helper.UnderLine(typeOf.Elem().Field(i).Name) val := valueOf.Elem().Field(i).Field(0).Field(0).Interface() ex.whereList = append(ex.whereList, WhereItem{Field: key, Opt: Eq, Val: val}) } @@ -712,7 +712,7 @@ func (ex *Executor) Having(dest interface{}) *Executor { for i := 0; i < typeOf.Elem().NumField(); i++ { isNotNull := valueOf.Elem().Field(i).Field(0).Field(1).Bool() if isNotNull { - key := aorm.UnderLine(typeOf.Elem().Field(i).Name) + key := helper.UnderLine(typeOf.Elem().Field(i).Name) val := valueOf.Elem().Field(i).Field(0).Field(0).Interface() ex.havingList = append(ex.havingList, WhereItem{Field: key, Opt: Eq, Val: val}) } @@ -912,7 +912,7 @@ func (ex *Executor) handleSet(dest interface{}, paramList []any) (string, []any) for i := 0; i < typeOf.Elem().NumField(); i++ { isNotNull := valueOf.Elem().Field(i).Field(0).Field(1).Bool() if isNotNull { - key := aorm.UnderLine(typeOf.Elem().Field(i).Name) + key := helper.UnderLine(typeOf.Elem().Field(i).Name) val := valueOf.Elem().Field(i).Field(0).Field(0).Interface() keys = append(keys, key+"=?") @@ -986,7 +986,7 @@ func handleLockForUpdate(isLock bool) string { func whereAndHaving(where []WhereItem, paramList []any) ([]string, []any) { var whereList []string for i := 0; i < len(where); i++ { - if "**Executor" == reflect.TypeOf(where[i].Val).String() { + if "**executor.Executor" == reflect.TypeOf(where[i].Val).String() { executor := *(**Executor)(unsafe.Pointer(reflect.ValueOf(where[i].Val).Pointer())) subSql, subParams := executor.GetSqlAndParams() @@ -1094,7 +1094,7 @@ func reflectTableName(typeOf reflect.Type, valueOf reflect.Value) string { return res[0].String() } else { arr := strings.Split(typeOf.String(), ".") - return aorm.UnderLine(arr[len(arr)-1]) + return helper.UnderLine(arr[len(arr)-1]) } } @@ -1110,7 +1110,7 @@ func getFieldNameMap(destValue reflect.Value, destType reflect.Type) map[string] func getScans(columnNameList []string, fieldNameMap map[string]int, destValue reflect.Value) []interface{} { var scans []interface{} for _, columnName := range columnNameList { - fieldName := aorm.CamelString(strings.ToLower(columnName)) + fieldName := helper.CamelString(strings.ToLower(columnName)) index, ok := fieldNameMap[fieldName] if ok { scans = append(scans, destValue.Field(index).Addr().Interface()) diff --git a/executor/model.go b/executor/executor.go similarity index 55% rename from executor/model.go rename to executor/executor.go index dca3735..0162731 100644 --- a/executor/model.go +++ b/executor/executor.go @@ -1,14 +1,8 @@ package executor -import "database/sql" - -// LinkCommon database/sql提供的库连接与事务,二者有很多方法是一致的,为了通用,抽象为该interface -type LinkCommon interface { - Exec(query string, args ...interface{}) (sql.Result, error) - Prepare(query string) (*sql.Stmt, error) - Query(query string, args ...interface{}) (*sql.Rows, error) - QueryRow(query string, args ...interface{}) *sql.Row -} +import ( + "github.com/tangpanqing/aorm/model" +) // ExpItem 将某子语句重命名为某字段 type ExpItem struct { @@ -19,7 +13,7 @@ type ExpItem struct { // Executor 查询记录所需要的条件 type Executor struct { //数据库操作连接 - LinkCommon LinkCommon + LinkCommon model.LinkCommon //查询参数 tableName string @@ -39,14 +33,6 @@ type Executor struct { sql string paramList []interface{} - //表属性 - opinionList []OpinionItem - //驱动名字 driverName string } - -type OpinionItem struct { - Key string - Val string -} diff --git a/str.go b/helper/str.go similarity index 98% rename from str.go rename to helper/str.go index e3b06a8..7fab0d3 100644 --- a/str.go +++ b/helper/str.go @@ -1,4 +1,4 @@ -package aorm +package helper import ( "unicode" diff --git a/migrate.go b/migrate.go deleted file mode 100644 index 4cae9e2..0000000 --- a/migrate.go +++ /dev/null @@ -1,456 +0,0 @@ -package aorm - -import ( - "github.com/tangpanqing/aorm/executor" - "github.com/tangpanqing/aorm/migrate_mysql" - "reflect" - "strings" -) - -func (ex *executor.Executor) Driver(driverName string) *executor.Executor { - ex.driverName = driverName - return ex -} - -func (ex *executor.Executor) Opinion(key string, val string) *executor.Executor { - if key == "COMMENT" { - val = "'" + val + "'" - } - - ex.opinionList = append(ex.opinionList, OpinionItem{Key: key, Val: val}) - - return ex -} - -//ShowCreateTable 获取创建表的ddl -func (ex *executor.Executor) ShowCreateTable(tableName string) string { - if ex.driverName == "mysql" { - cr := migrate_mysql.MigrateExecutor{} - return cr.SetEx(ex).ShowCreateTable(tableName) - } - return "" -} - -// AutoMigrate 迁移数据库结构,需要输入数据库名,表名自动获取 -func (ex *Executor) AutoMigrate(dest interface{}) { - typeOf := reflect.TypeOf(dest) - arr := strings.Split(typeOf.String(), ".") - tableName := UnderLine(arr[len(arr)-1]) - - ex.migrateCommon(tableName, typeOf) -} - -// Migrate 自动迁移数据库结构,需要输入数据库名,表名 -func (ex *Executor) Migrate(tableName string, dest interface{}) { - typeOf := reflect.TypeOf(dest) - ex.migrateCommon(tableName, typeOf) -} - -func (ex *Executor) migrateCommon(tableName string, typeOf reflect.Type) { - if ex.driverName == "mysql" { - cr := migrate_mysql.MigrateExecutor{} - cr.SetEx(ex).MigrateCommon(tableName, typeOf) - } - - if ex.driverName == "sqlite3" { - //cr := migrate_sqlite3.MigrateExecutor{ - // Ex: ex, - //} - //cr.MigrateCommon(tableName, typeOf) - } -} - -func (ex *Executor) GetOpinionList() []OpinionItem { - return ex.opinionList -} - -// -//func (ex *Executor) getTableFromCode(tableName string) Table { -// var tableFromCode Table -// tableFromCode.TableName = StringFrom(tableName) -// tableFromCode.Engine = StringFrom(ex.getValFromOpinion("ENGINE", "MyISAM")) -// tableFromCode.TableComment = StringFrom(ex.getValFromOpinion("COMMENT", "")) -// -// return tableFromCode -//} -// -//func (ex *Executor) getColumnsFromCode(typeOf reflect.Type) []Column { -// var columnsFromCode []Column -// for i := 0; i < typeOf.Elem().NumField(); i++ { -// fieldName := UnderLine(typeOf.Elem().Field(i).Name) -// fieldType := typeOf.Elem().Field(i).Type.Name() -// fieldMap := getTagMap(typeOf.Elem().Field(i).Tag.Get("aorm")) -// columnsFromCode = append(columnsFromCode, getColumnFromCode(fieldName, fieldType, fieldMap)) -// } -// -// return columnsFromCode -//} -// -//func (ex *Executor) getIndexsFromCode(typeOf reflect.Type, tableFromCode Table) []Index { -// var indexsFromCode []Index -// for i := 0; i < typeOf.Elem().NumField(); i++ { -// fieldName := UnderLine(typeOf.Elem().Field(i).Name) -// fieldMap := getTagMap(typeOf.Elem().Field(i).Tag.Get("aorm")) -// -// _, primaryIs := fieldMap["primary"] -// if primaryIs { -// indexsFromCode = append(indexsFromCode, Index{ -// NonUnique: 0, -// ColumnName: fieldName, -// KeyName: "PRIMARY", -// }) -// } -// -// _, uniqueIndexIs := fieldMap["unique"] -// if uniqueIndexIs { -// indexsFromCode = append(indexsFromCode, Index{ -// NonUnique: 0, -// ColumnName: fieldName, -// KeyName: "idx_" + tableFromCode.TableName.String + "_" + fieldName, -// }) -// } -// -// _, indexIs := fieldMap["index"] -// if indexIs { -// indexsFromCode = append(indexsFromCode, Index{ -// NonUnique: 1, -// ColumnName: fieldName, -// KeyName: "idx_" + tableFromCode.TableName.String + "_" + fieldName, -// }) -// } -// } -// -// return indexsFromCode -//} -// -//func (ex *Executor) getColumnsFromDb(dbName string, tableName string) []Column { -// var columnsFromDb []Column -// -// sqlColumn := "SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH as Max_Length,COLUMN_DEFAULT,COLUMN_COMMENT,EXTRA,IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA =" + "'" + dbName + "' AND TABLE_NAME =" + "'" + tableName + "'" -// ex.RawSql(sqlColumn).GetMany(&columnsFromDb) -// -// for j := 0; j < len(columnsFromDb); j++ { -// if columnsFromDb[j].DataType.String == "text" && columnsFromDb[j].MaxLength.Int64 == 65535 { -// columnsFromDb[j].MaxLength = IntFrom(0) -// } -// } -// -// return columnsFromDb -//} -// -//func (ex *Executor) getIndexsFromDb(tableName string) []Index { -// sqlIndex := "SHOW INDEXES FROM " + tableName -// -// var indexsFromDb []Index -// ex.RawSql(sqlIndex).GetMany(&indexsFromDb) -// -// return indexsFromDb -//} -// -//// 修改表 -//func (ex *Executor) modifyTable(tableFromCode Table, columnsFromCode []Column, indexsFromCode []Index, tableFromDb Table, columnsFromDb []Column, indexsFromDb []Index) { -// if tableFromCode.Engine != tableFromDb.Engine { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " Engine " + tableFromCode.Engine.String -// _, err := ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改表:" + sql) -// } -// } -// -// if tableFromCode.TableComment != tableFromDb.TableComment { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " Comment " + tableFromCode.TableComment.String -// _, err := ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改表:" + sql) -// } -// } -// -// for i := 0; i < len(columnsFromCode); i++ { -// isFind := 0 -// columnCode := columnsFromCode[i] -// -// for j := 0; j < len(columnsFromDb); j++ { -// columnDb := columnsFromDb[j] -// if columnCode.ColumnName == columnDb.ColumnName { -// isFind = 1 -// if columnCode.DataType.String != columnDb.DataType.String || -// columnCode.MaxLength.Int64 != columnDb.MaxLength.Int64 || -// columnCode.ColumnComment.String != columnDb.ColumnComment.String || -// columnCode.Extra.String != columnDb.Extra.String || -// columnCode.ColumnDefault.String != columnDb.ColumnDefault.String { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " MODIFY " + getColumnStr(columnCode) -// _, err := ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改属性:" + sql) -// } -// } -// } -// } -// -// if isFind == 0 { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " ADD " + getColumnStr(columnCode) -// _, err := ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("增加属性:" + sql) -// } -// } -// } -// -// for i := 0; i < len(indexsFromCode); i++ { -// isFind := 0 -// indexCode := indexsFromCode[i] -// -// for j := 0; j < len(indexsFromDb); j++ { -// indexDb := indexsFromDb[j] -// if indexCode.ColumnName == indexDb.ColumnName { -// isFind = 1 -// if indexCode.KeyName != indexDb.KeyName || indexCode.NonUnique != indexDb.NonUnique { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " MODIFY " + getIndexStr(indexCode) -// _, err := ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改索引:" + sql) -// } -// } -// } -// } -// -// if isFind == 0 { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " ADD " + getIndexStr(indexCode) -// _, err := ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("增加索引:" + sql) -// } -// } -// } -//} -// -//// 创建表 -//func (ex *Executor) createTable(tableFromCode Table, columnsFromCode []Column, indexsFromCode []Index) { -// var fieldArr []string -// -// for i := 0; i < len(columnsFromCode); i++ { -// column := columnsFromCode[i] -// fieldArr = append(fieldArr, getColumnStr(column)) -// } -// -// for i := 0; i < len(indexsFromCode); i++ { -// index := indexsFromCode[i] -// fieldArr = append(fieldArr, getIndexStr(index)) -// } -// -// sqlStr := "CREATE TABLE `" + tableFromCode.TableName.String + "` (\n" + strings.Join(fieldArr, ",\n") + "\n) " + getTableInfoFromCode(tableFromCode) + ";" -// _, err := ex.Exec(sqlStr) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("创建表:" + tableFromCode.TableName.String) -// } -//} -// -//// -//func (ex *Executor) getValFromOpinion(key string, def string) string { -// for i := 0; i < len(ex.opinionList); i++ { -// opinionItem := ex.opinionList[i] -// if opinionItem.Key == key { -// def = opinionItem.Val -// } -// } -// return def -//} -// -//func getTableInfoFromCode(tableFromCode Table) string { -// return " ENGINE " + tableFromCode.Engine.String + " COMMENT " + tableFromCode.TableComment.String -//} -// -//// 获得某列的结构 -//func getColumnFromCode(fieldName string, fieldType string, fieldMap map[string]string) Column { -// var column Column -// //字段名 -// column.ColumnName = StringFrom(fieldName) -// //字段数据类型 -// column.DataType = StringFrom(getDataType(fieldType, fieldMap)) -// //字段数据长度 -// column.MaxLength = IntFrom(int64(getMaxLength(column.DataType.String, fieldMap))) -// //字段是否可以为空 -// column.IsNullable = StringFrom(getNullAble(fieldMap)) -// //字段注释 -// column.ColumnComment = StringFrom(getComment(fieldMap)) -// //扩展信息 -// column.Extra = StringFrom(getExtra(fieldMap)) -// //默认信息 -// column.ColumnDefault = StringFrom(getDefaultVal(fieldMap)) -// -// return column -//} -// -//// 转换tag成map -//func getTagMap(fieldTag string) map[string]string { -// var fieldMap = make(map[string]string) -// if "" != fieldTag { -// tagArr := strings.Split(fieldTag, ";") -// for j := 0; j < len(tagArr); j++ { -// tagArrArr := strings.Split(tagArr[j], ":") -// fieldMap[tagArrArr[0]] = "" -// if len(tagArrArr) > 1 { -// fieldMap[tagArrArr[0]] = tagArrArr[1] -// } -// } -// } -// return fieldMap -//} -// -//func getColumnStr(column Column) string { -// var strArr []string -// strArr = append(strArr, column.ColumnName.String) -// if column.MaxLength.Int64 == 0 { -// if column.DataType.String == "varchar" { -// strArr = append(strArr, column.DataType.String+"(255)") -// } else { -// strArr = append(strArr, column.DataType.String) -// } -// } else { -// strArr = append(strArr, column.DataType.String+"("+strconv.Itoa(int(column.MaxLength.Int64))+")") -// } -// -// if column.ColumnDefault.String != "" { -// strArr = append(strArr, "DEFAULT '"+column.ColumnDefault.String+"'") -// } -// -// if column.IsNullable.String == "NO" { -// strArr = append(strArr, "NOT NULL") -// } -// -// if column.ColumnComment.String != "" { -// strArr = append(strArr, "COMMENT '"+column.ColumnComment.String+"'") -// } -// -// if column.Extra.String != "" { -// strArr = append(strArr, column.Extra.String) -// } -// -// return strings.Join(strArr, " ") -//} -// -//func getIndexStr(index Index) string { -// var strArr []string -// -// if "PRIMARY" == index.KeyName { -// strArr = append(strArr, index.KeyName) -// strArr = append(strArr, "KEY") -// strArr = append(strArr, "(`"+index.ColumnName+"`)") -// } else { -// if 0 == index.NonUnique { -// strArr = append(strArr, "Unique") -// strArr = append(strArr, index.KeyName) -// strArr = append(strArr, "(`"+index.ColumnName+"`)") -// } else { -// strArr = append(strArr, "Index") -// strArr = append(strArr, index.KeyName) -// strArr = append(strArr, "(`"+index.ColumnName+"`)") -// } -// } -// -// return strings.Join(strArr, " ") -//} -// -////将对象属性类型转换数据库字段数据类型 -//func getDataType(fieldType string, fieldMap map[string]string) string { -// var DataType string -// -// dataTypeVal, dataTypeOk := fieldMap["type"] -// if dataTypeOk { -// DataType = dataTypeVal -// } else { -// if "Int" == fieldType { -// DataType = "int" -// } -// if "String" == fieldType { -// DataType = "varchar" -// } -// if "Bool" == fieldType { -// DataType = "tinyint" -// } -// if "Time" == fieldType { -// DataType = "datetime" -// } -// if "Float" == fieldType { -// DataType = "float" -// } -// } -// -// return DataType -//} -// -//func getMaxLength(DataType string, fieldMap map[string]string) int { -// var MaxLength int -// -// maxLengthVal, maxLengthOk := fieldMap["size"] -// if maxLengthOk { -// num, _ := strconv.Atoi(maxLengthVal) -// MaxLength = num -// } else { -// MaxLength = 0 -// if "varchar" == DataType { -// MaxLength = 255 -// } -// } -// -// return MaxLength -//} -// -//func getNullAble(fieldMap map[string]string) string { -// var IsNullable string -// -// _, primaryOk := fieldMap["primary"] -// if primaryOk { -// IsNullable = "NO" -// } else { -// _, ok := fieldMap["not null"] -// if ok { -// IsNullable = "NO" -// } else { -// IsNullable = "YES" -// } -// } -// -// return IsNullable -//} -// -//func getComment(fieldMap map[string]string) string { -// commentVal, commentIs := fieldMap["comment"] -// if commentIs { -// return commentVal -// } -// -// return "" -//} -// -//func getExtra(fieldMap map[string]string) string { -// _, commentIs := fieldMap["auto_increment"] -// if commentIs { -// return "auto_increment" -// } -// -// return "" -//} -// -//func getDefaultVal(fieldMap map[string]string) string { -// defaultVal, defaultIs := fieldMap["default"] -// if defaultIs { -// return defaultVal -// } -// -// return "" -//} diff --git a/migrate_mysql/migrate.go b/migrate_mysql/migrate.go index 3d505f9..7b9dc38 100644 --- a/migrate_mysql/migrate.go +++ b/migrate_mysql/migrate.go @@ -1,9 +1,14 @@ package migrate_mysql import ( + "fmt" "github.com/tangpanqing/aorm/executor" + "github.com/tangpanqing/aorm/helper" + "github.com/tangpanqing/aorm/model" "github.com/tangpanqing/aorm/null" "reflect" + "strconv" + "strings" ) type Table struct { @@ -30,443 +35,443 @@ type Index struct { //MigrateExecutor 定义结构 type MigrateExecutor struct { - ex *executor.Executor -} + //驱动名字 + DriverName string -//SetEx 设置ex执行者 -func (mm *MigrateExecutor) SetEx(ex *executor.Executor) *MigrateExecutor { - mm.ex = ex - return mm + //表属性 + OpinionList []model.OpinionItem + + //执行者 + Ex *executor.Executor } //ShowCreateTable 查看创建表的ddl -//func (mm *MigrateExecutor) ShowCreateTable(tableName string) string { -// var str string -// mm.ex.RawSql("show create table "+tableName).Value("Create Table", &str) -// return str -//} +func (mm *MigrateExecutor) ShowCreateTable(tableName string) string { + var str string + mm.Ex.RawSql("show create table "+tableName).Value("Create Table", &str) + return str +} //MigrateCommon 迁移的主要过程 func (mm *MigrateExecutor) MigrateCommon(tableName string, typeOf reflect.Type) error { - //tableFromCode := mm.getTableFromCode(tableName) - //columnsFromCode := mm.getColumnsFromCode(typeOf) - //indexesFromCode := mm.getIndexesFromCode(typeOf, tableFromCode) - // - //dbName, dbErr := mm.getDbName() - //if dbErr != nil { - // return dbErr - //} - // - //tablesFromDb := mm.getTableFromDb(dbName, tableName) - //if len(tablesFromDb) != 0 { - // tableFromDb := tablesFromDb[0] - // columnsFromDb := mm.getColumnsFromDb(dbName, tableName) - // indexsFromDb := mm.getIndexesFromDb(tableName) - // - // mm.modifyTable(tableFromCode, columnsFromCode, indexesFromCode, tableFromDb, columnsFromDb, indexsFromDb) - //} else { - // mm.createTable(tableFromCode, columnsFromCode, indexesFromCode) - //} + tableFromCode := mm.getTableFromCode(tableName) + columnsFromCode := mm.getColumnsFromCode(typeOf) + indexesFromCode := mm.getIndexesFromCode(typeOf, tableFromCode) + + dbName, dbErr := mm.getDbName() + if dbErr != nil { + return dbErr + } + + tablesFromDb := mm.getTableFromDb(dbName, tableName) + if len(tablesFromDb) != 0 { + tableFromDb := tablesFromDb[0] + columnsFromDb := mm.getColumnsFromDb(dbName, tableName) + indexsFromDb := mm.getIndexesFromDb(tableName) + + mm.modifyTable(tableFromCode, columnsFromCode, indexesFromCode, tableFromDb, columnsFromDb, indexsFromDb) + } else { + mm.createTable(tableFromCode, columnsFromCode, indexesFromCode) + } return nil } -// -//func (mm *MigrateExecutor) getTableFromCode(tableName string) Table { -// var tableFromCode Table -// tableFromCode.TableName = aorm.StringFrom(tableName) -// tableFromCode.Engine = aorm.StringFrom(mm.getOpinionVal("ENGINE", "MyISAM")) -// tableFromCode.TableComment = aorm.StringFrom(mm.getOpinionVal("COMMENT", "")) -// -// return tableFromCode -//} -// -//func (mm *MigrateExecutor) getColumnsFromCode(typeOf reflect.Type) []Column { -// var columnsFromCode []Column -// for i := 0; i < typeOf.Elem().NumField(); i++ { -// fieldName := aorm.UnderLine(typeOf.Elem().Field(i).Name) -// fieldType := typeOf.Elem().Field(i).Type.Name() -// fieldMap := getTagMap(typeOf.Elem().Field(i).Tag.Get("aorm")) -// columnsFromCode = append(columnsFromCode, Column{ -// ColumnName: aorm.StringFrom(fieldName), -// DataType: aorm.StringFrom(getDataType(fieldType, fieldMap)), -// MaxLength: aorm.IntFrom(int64(getMaxLength(getDataType(fieldType, fieldMap), fieldMap))), -// IsNullable: aorm.StringFrom(getNullAble(fieldMap)), -// ColumnComment: aorm.StringFrom(getComment(fieldMap)), -// Extra: aorm.StringFrom(getExtra(fieldMap)), -// ColumnDefault: aorm.StringFrom(getDefaultVal(fieldMap)), -// }) -// } -// -// return columnsFromCode -//} -// -//func (mm *MigrateExecutor) getIndexesFromCode(typeOf reflect.Type, tableFromCode Table) []Index { -// var indexesFromCode []Index -// for i := 0; i < typeOf.Elem().NumField(); i++ { -// fieldName := aorm.UnderLine(typeOf.Elem().Field(i).Name) -// fieldMap := getTagMap(typeOf.Elem().Field(i).Tag.Get("aorm")) -// -// _, primaryIs := fieldMap["primary"] -// if primaryIs { -// indexesFromCode = append(indexesFromCode, Index{ -// NonUnique: aorm.IntFrom(0), -// ColumnName: aorm.StringFrom(fieldName), -// KeyName: aorm.StringFrom("PRIMARY"), -// }) -// } -// -// _, uniqueIndexIs := fieldMap["unique"] -// if uniqueIndexIs { -// indexesFromCode = append(indexesFromCode, Index{ -// NonUnique: aorm.IntFrom(0), -// ColumnName: aorm.StringFrom(fieldName), -// KeyName: aorm.StringFrom("idx_" + tableFromCode.TableName.String + "_" + fieldName), -// }) -// } -// -// _, indexIs := fieldMap["index"] -// if indexIs { -// indexesFromCode = append(indexesFromCode, Index{ -// NonUnique: aorm.IntFrom(1), -// ColumnName: aorm.StringFrom(fieldName), -// KeyName: aorm.StringFrom("idx_" + tableFromCode.TableName.String + "_" + fieldName), -// }) -// } -// } -// -// return indexesFromCode -//} -// -//func (mm *MigrateExecutor) getDbName() (string, error) { -// //获取数据库名称 -// var dbName string -// err := mm.ex.RawSql("SELECT DATABASE()").Value("DATABASE()", &dbName) -// if err != nil { -// return "", err -// } -// -// return dbName, nil -//} -// -//func (mm *MigrateExecutor) getTableFromDb(dbName string, tableName string) []Table { -// sql := "SELECT TABLE_NAME,ENGINE,TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA =" + "'" + dbName + "' AND TABLE_NAME =" + "'" + tableName + "'" -// var dataList []Table -// mm.ex.RawSql(sql).GetMany(&dataList) -// for i := 0; i < len(dataList); i++ { -// dataList[i].TableComment = aorm.StringFrom("'" + dataList[i].TableComment.String + "'") -// } -// -// return dataList -//} -// -//func (mm *MigrateExecutor) getColumnsFromDb(dbName string, tableName string) []Column { -// var columnsFromDb []Column -// -// sqlColumn := "SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH as Max_Length,COLUMN_DEFAULT,COLUMN_COMMENT,EXTRA,IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA =" + "'" + dbName + "' AND TABLE_NAME =" + "'" + tableName + "'" -// mm.ex.RawSql(sqlColumn).GetMany(&columnsFromDb) -// -// for j := 0; j < len(columnsFromDb); j++ { -// if columnsFromDb[j].DataType.String == "text" && columnsFromDb[j].MaxLength.Int64 == 65535 { -// columnsFromDb[j].MaxLength = aorm.IntFrom(0) -// } -// } -// -// return columnsFromDb -//} -// -//func (mm *MigrateExecutor) getIndexesFromDb(tableName string) []Index { -// sqlIndex := "SHOW INDEXES FROM " + tableName -// -// var indexsFromDb []Index -// mm.ex.RawSql(sqlIndex).GetMany(&indexsFromDb) -// -// return indexsFromDb -//} -// -//func (mm *MigrateExecutor) modifyTable(tableFromCode Table, columnsFromCode []Column, indexesFromCode []Index, tableFromDb Table, columnsFromDb []Column, indexsFromDb []Index) { -// if tableFromCode.Engine != tableFromDb.Engine { -// mm.modifyTableEngine(tableFromCode) -// } -// -// if tableFromCode.TableComment != tableFromDb.TableComment { -// mm.modifyTableComment(tableFromCode) -// } -// -// for i := 0; i < len(columnsFromCode); i++ { -// isFind := 0 -// columnCode := columnsFromCode[i] -// -// for j := 0; j < len(columnsFromDb); j++ { -// columnDb := columnsFromDb[j] -// if columnCode.ColumnName == columnDb.ColumnName { -// isFind = 1 -// if columnCode.DataType.String != columnDb.DataType.String || -// columnCode.MaxLength.Int64 != columnDb.MaxLength.Int64 || -// columnCode.ColumnComment.String != columnDb.ColumnComment.String || -// columnCode.Extra.String != columnDb.Extra.String || -// columnCode.ColumnDefault.String != columnDb.ColumnDefault.String { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " MODIFY " + getColumnStr(columnCode) -// _, err := mm.ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改属性:" + sql) -// } -// } -// } -// } -// -// if isFind == 0 { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " ADD " + getColumnStr(columnCode) -// _, err := mm.ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("增加属性:" + sql) -// } -// } -// } -// -// for i := 0; i < len(indexesFromCode); i++ { -// isFind := 0 -// indexCode := indexesFromCode[i] -// -// for j := 0; j < len(indexsFromDb); j++ { -// indexDb := indexsFromDb[j] -// if indexCode.ColumnName == indexDb.ColumnName { -// isFind = 1 -// if indexCode.KeyName != indexDb.KeyName || indexCode.NonUnique != indexDb.NonUnique { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " MODIFY " + getIndexStr(indexCode) -// _, err := mm.ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改索引:" + sql) -// } -// } -// } -// } -// -// if isFind == 0 { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " ADD " + getIndexStr(indexCode) -// _, err := mm.ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("增加索引:" + sql) -// } -// } -// } -//} -// -//func (mm *MigrateExecutor) modifyTableEngine(tableFromCode Table) { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " Engine " + tableFromCode.Engine.String -// _, err := mm.ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改表:" + sql) -// } -//} -// -//func (mm *MigrateExecutor) modifyTableComment(tableFromCode Table) { -// sql := "ALTER TABLE " + tableFromCode.TableName.String + " Comment " + tableFromCode.TableComment.String -// _, err := mm.ex.Exec(sql) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("修改表:" + sql) -// } -//} -// -//func (mm *MigrateExecutor) createTable(tableFromCode Table, columnsFromCode []Column, indexesFromCode []Index) { -// var fieldArr []string -// -// for i := 0; i < len(columnsFromCode); i++ { -// column := columnsFromCode[i] -// fieldArr = append(fieldArr, getColumnStr(column)) -// } -// -// for i := 0; i < len(indexesFromCode); i++ { -// index := indexesFromCode[i] -// fieldArr = append(fieldArr, getIndexStr(index)) -// } -// -// sqlStr := "CREATE TABLE `" + tableFromCode.TableName.String + "` (\n" + strings.Join(fieldArr, ",\n") + "\n) " + " ENGINE " + tableFromCode.Engine.String + " COMMENT " + tableFromCode.TableComment.String + ";" -// _, err := mm.ex.Exec(sqlStr) -// if err != nil { -// fmt.Println(err) -// } else { -// fmt.Println("创建表:" + tableFromCode.TableName.String) -// } -//} -// -//func (mm *MigrateExecutor) getOpinionVal(key string, def string) string { -// opinions := mm.ex.GetOpinionList() -// for i := 0; i < len(opinions); i++ { -// opinionItem := opinions[i] -// if opinionItem.Key == key { -// def = opinionItem.Val -// } -// } -// return def -//} -// -//func getTagMap(fieldTag string) map[string]string { -// var fieldMap = make(map[string]string) -// if "" != fieldTag { -// tagArr := strings.Split(fieldTag, ";") -// for j := 0; j < len(tagArr); j++ { -// tagArrArr := strings.Split(tagArr[j], ":") -// fieldMap[tagArrArr[0]] = "" -// if len(tagArrArr) > 1 { -// fieldMap[tagArrArr[0]] = tagArrArr[1] -// } -// } -// } -// return fieldMap -//} -// -//func getColumnStr(column Column) string { -// var strArr []string -// strArr = append(strArr, column.ColumnName.String) -// if column.MaxLength.Int64 == 0 { -// if column.DataType.String == "varchar" { -// strArr = append(strArr, column.DataType.String+"(255)") -// } else { -// strArr = append(strArr, column.DataType.String) -// } -// } else { -// strArr = append(strArr, column.DataType.String+"("+strconv.Itoa(int(column.MaxLength.Int64))+")") -// } -// -// if column.ColumnDefault.String != "" { -// strArr = append(strArr, "DEFAULT '"+column.ColumnDefault.String+"'") -// } -// -// if column.IsNullable.String == "NO" { -// strArr = append(strArr, "NOT NULL") -// } -// -// if column.ColumnComment.String != "" { -// strArr = append(strArr, "COMMENT '"+column.ColumnComment.String+"'") -// } -// -// if column.Extra.String != "" { -// strArr = append(strArr, column.Extra.String) -// } -// -// return strings.Join(strArr, " ") -//} -// -//func getIndexStr(index Index) string { -// var strArr []string -// -// if "PRIMARY" == index.KeyName.String { -// strArr = append(strArr, index.KeyName.String) -// strArr = append(strArr, "KEY") -// strArr = append(strArr, "(`"+index.ColumnName.String+"`)") -// } else { -// if 0 == index.NonUnique.Int64 { -// strArr = append(strArr, "Unique") -// strArr = append(strArr, index.KeyName.String) -// strArr = append(strArr, "(`"+index.ColumnName.String+"`)") -// } else { -// strArr = append(strArr, "Index") -// strArr = append(strArr, index.KeyName.String) -// strArr = append(strArr, "(`"+index.ColumnName.String+"`)") -// } -// } -// -// return strings.Join(strArr, " ") -//} -// -//func getDataType(fieldType string, fieldMap map[string]string) string { -// var DataType string -// -// dataTypeVal, dataTypeOk := fieldMap["type"] -// if dataTypeOk { -// DataType = dataTypeVal -// } else { -// if "Int" == fieldType { -// DataType = "int" -// } -// if "String" == fieldType { -// DataType = "varchar" -// } -// if "Bool" == fieldType { -// DataType = "tinyint" -// } -// if "Time" == fieldType { -// DataType = "datetime" -// } -// if "Float" == fieldType { -// DataType = "float" -// } -// } -// -// return DataType -//} -// -//func getMaxLength(DataType string, fieldMap map[string]string) int { -// var MaxLength int -// -// maxLengthVal, maxLengthOk := fieldMap["size"] -// if maxLengthOk { -// num, _ := strconv.Atoi(maxLengthVal) -// MaxLength = num -// } else { -// MaxLength = 0 -// if "varchar" == DataType { -// MaxLength = 255 -// } -// } -// -// return MaxLength -//} -// -//func getNullAble(fieldMap map[string]string) string { -// var IsNullable string -// -// _, primaryOk := fieldMap["primary"] -// if primaryOk { -// IsNullable = "NO" -// } else { -// _, ok := fieldMap["not null"] -// if ok { -// IsNullable = "NO" -// } else { -// IsNullable = "YES" -// } -// } -// -// return IsNullable -//} -// -//func getComment(fieldMap map[string]string) string { -// commentVal, commentIs := fieldMap["comment"] -// if commentIs { -// return commentVal -// } -// -// return "" -//} -// -//func getExtra(fieldMap map[string]string) string { -// _, commentIs := fieldMap["auto_increment"] -// if commentIs { -// return "auto_increment" -// } -// -// return "" -//} -// -//func getDefaultVal(fieldMap map[string]string) string { -// defaultVal, defaultIs := fieldMap["default"] -// if defaultIs { -// return defaultVal -// } -// -// return "" -//} +func (mm *MigrateExecutor) getTableFromCode(tableName string) Table { + var tableFromCode Table + tableFromCode.TableName = null.StringFrom(tableName) + tableFromCode.Engine = null.StringFrom(mm.getOpinionVal("ENGINE", "MyISAM")) + tableFromCode.TableComment = null.StringFrom(mm.getOpinionVal("COMMENT", "")) + + return tableFromCode +} + +func (mm *MigrateExecutor) getColumnsFromCode(typeOf reflect.Type) []Column { + var columnsFromCode []Column + for i := 0; i < typeOf.Elem().NumField(); i++ { + fieldName := helper.UnderLine(typeOf.Elem().Field(i).Name) + fieldType := typeOf.Elem().Field(i).Type.Name() + fieldMap := getTagMap(typeOf.Elem().Field(i).Tag.Get("aorm")) + columnsFromCode = append(columnsFromCode, Column{ + ColumnName: null.StringFrom(fieldName), + DataType: null.StringFrom(getDataType(fieldType, fieldMap)), + MaxLength: null.IntFrom(int64(getMaxLength(getDataType(fieldType, fieldMap), fieldMap))), + IsNullable: null.StringFrom(getNullAble(fieldMap)), + ColumnComment: null.StringFrom(getComment(fieldMap)), + Extra: null.StringFrom(getExtra(fieldMap)), + ColumnDefault: null.StringFrom(getDefaultVal(fieldMap)), + }) + } + + return columnsFromCode +} + +func (mm *MigrateExecutor) getIndexesFromCode(typeOf reflect.Type, tableFromCode Table) []Index { + var indexesFromCode []Index + for i := 0; i < typeOf.Elem().NumField(); i++ { + fieldName := helper.UnderLine(typeOf.Elem().Field(i).Name) + fieldMap := getTagMap(typeOf.Elem().Field(i).Tag.Get("aorm")) + + _, primaryIs := fieldMap["primary"] + if primaryIs { + indexesFromCode = append(indexesFromCode, Index{ + NonUnique: null.IntFrom(0), + ColumnName: null.StringFrom(fieldName), + KeyName: null.StringFrom("PRIMARY"), + }) + } + + _, uniqueIndexIs := fieldMap["unique"] + if uniqueIndexIs { + indexesFromCode = append(indexesFromCode, Index{ + NonUnique: null.IntFrom(0), + ColumnName: null.StringFrom(fieldName), + KeyName: null.StringFrom("idx_" + tableFromCode.TableName.String + "_" + fieldName), + }) + } + + _, indexIs := fieldMap["index"] + if indexIs { + indexesFromCode = append(indexesFromCode, Index{ + NonUnique: null.IntFrom(1), + ColumnName: null.StringFrom(fieldName), + KeyName: null.StringFrom("idx_" + tableFromCode.TableName.String + "_" + fieldName), + }) + } + } + + return indexesFromCode +} + +func (mm *MigrateExecutor) getDbName() (string, error) { + //获取数据库名称 + var dbName string + err := mm.Ex.RawSql("SELECT DATABASE()").Value("DATABASE()", &dbName) + if err != nil { + return "", err + } + + return dbName, nil +} + +func (mm *MigrateExecutor) getTableFromDb(dbName string, tableName string) []Table { + sql := "SELECT TABLE_NAME,ENGINE,TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA =" + "'" + dbName + "' AND TABLE_NAME =" + "'" + tableName + "'" + var dataList []Table + mm.Ex.RawSql(sql).GetMany(&dataList) + for i := 0; i < len(dataList); i++ { + dataList[i].TableComment = null.StringFrom("'" + dataList[i].TableComment.String + "'") + } + + return dataList +} + +func (mm *MigrateExecutor) getColumnsFromDb(dbName string, tableName string) []Column { + var columnsFromDb []Column + + sqlColumn := "SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH as Max_Length,COLUMN_DEFAULT,COLUMN_COMMENT,EXTRA,IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA =" + "'" + dbName + "' AND TABLE_NAME =" + "'" + tableName + "'" + mm.Ex.RawSql(sqlColumn).GetMany(&columnsFromDb) + + for j := 0; j < len(columnsFromDb); j++ { + if columnsFromDb[j].DataType.String == "text" && columnsFromDb[j].MaxLength.Int64 == 65535 { + columnsFromDb[j].MaxLength = null.IntFrom(0) + } + } + + return columnsFromDb +} + +func (mm *MigrateExecutor) getIndexesFromDb(tableName string) []Index { + sqlIndex := "SHOW INDEXES FROM " + tableName + + var indexsFromDb []Index + mm.Ex.RawSql(sqlIndex).GetMany(&indexsFromDb) + + return indexsFromDb +} + +func (mm *MigrateExecutor) modifyTable(tableFromCode Table, columnsFromCode []Column, indexesFromCode []Index, tableFromDb Table, columnsFromDb []Column, indexesFromDb []Index) { + if tableFromCode.Engine != tableFromDb.Engine { + mm.modifyTableEngine(tableFromCode) + } + + if tableFromCode.TableComment != tableFromDb.TableComment { + mm.modifyTableComment(tableFromCode) + } + + for i := 0; i < len(columnsFromCode); i++ { + isFind := 0 + columnCode := columnsFromCode[i] + + for j := 0; j < len(columnsFromDb); j++ { + columnDb := columnsFromDb[j] + if columnCode.ColumnName == columnDb.ColumnName { + isFind = 1 + if columnCode.DataType.String != columnDb.DataType.String || + columnCode.MaxLength.Int64 != columnDb.MaxLength.Int64 || + columnCode.ColumnComment.String != columnDb.ColumnComment.String || + columnCode.Extra.String != columnDb.Extra.String || + columnCode.ColumnDefault.String != columnDb.ColumnDefault.String { + sql := "ALTER TABLE " + tableFromCode.TableName.String + " MODIFY " + getColumnStr(columnCode) + _, err := mm.Ex.Exec(sql) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("修改属性:" + sql) + } + } + } + } + + if isFind == 0 { + sql := "ALTER TABLE " + tableFromCode.TableName.String + " ADD " + getColumnStr(columnCode) + _, err := mm.Ex.Exec(sql) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("增加属性:" + sql) + } + } + } + + for i := 0; i < len(indexesFromCode); i++ { + isFind := 0 + indexCode := indexesFromCode[i] + + for j := 0; j < len(indexesFromDb); j++ { + indexDb := indexesFromDb[j] + if indexCode.ColumnName == indexDb.ColumnName { + isFind = 1 + if indexCode.KeyName != indexDb.KeyName || indexCode.NonUnique != indexDb.NonUnique { + sql := "ALTER TABLE " + tableFromCode.TableName.String + " MODIFY " + getIndexStr(indexCode) + _, err := mm.Ex.Exec(sql) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("修改索引:" + sql) + } + } + } + } + + if isFind == 0 { + sql := "ALTER TABLE " + tableFromCode.TableName.String + " ADD " + getIndexStr(indexCode) + _, err := mm.Ex.Exec(sql) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("增加索引:" + sql) + } + } + } +} + +func (mm *MigrateExecutor) modifyTableEngine(tableFromCode Table) { + sql := "ALTER TABLE " + tableFromCode.TableName.String + " Engine " + tableFromCode.Engine.String + _, err := mm.Ex.Exec(sql) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("修改表:" + sql) + } +} + +func (mm *MigrateExecutor) modifyTableComment(tableFromCode Table) { + sql := "ALTER TABLE " + tableFromCode.TableName.String + " Comment " + tableFromCode.TableComment.String + _, err := mm.Ex.Exec(sql) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("修改表:" + sql) + } +} + +func (mm *MigrateExecutor) createTable(tableFromCode Table, columnsFromCode []Column, indexesFromCode []Index) { + var fieldArr []string + + for i := 0; i < len(columnsFromCode); i++ { + column := columnsFromCode[i] + fieldArr = append(fieldArr, getColumnStr(column)) + } + + for i := 0; i < len(indexesFromCode); i++ { + index := indexesFromCode[i] + fieldArr = append(fieldArr, getIndexStr(index)) + } + + sqlStr := "CREATE TABLE `" + tableFromCode.TableName.String + "` (\n" + strings.Join(fieldArr, ",\n") + "\n) " + " ENGINE " + tableFromCode.Engine.String + " COMMENT " + tableFromCode.TableComment.String + ";" + _, err := mm.Ex.Exec(sqlStr) + if err != nil { + fmt.Println(err) + } else { + fmt.Println("创建表:" + tableFromCode.TableName.String) + } +} + +func (mm *MigrateExecutor) getOpinionVal(key string, def string) string { + opinions := mm.OpinionList + for i := 0; i < len(opinions); i++ { + opinionItem := opinions[i] + if opinionItem.Key == key { + def = opinionItem.Val + } + } + return def +} + +func getTagMap(fieldTag string) map[string]string { + var fieldMap = make(map[string]string) + if "" != fieldTag { + tagArr := strings.Split(fieldTag, ";") + for j := 0; j < len(tagArr); j++ { + tagArrArr := strings.Split(tagArr[j], ":") + fieldMap[tagArrArr[0]] = "" + if len(tagArrArr) > 1 { + fieldMap[tagArrArr[0]] = tagArrArr[1] + } + } + } + return fieldMap +} + +func getColumnStr(column Column) string { + var strArr []string + strArr = append(strArr, column.ColumnName.String) + if column.MaxLength.Int64 == 0 { + if column.DataType.String == "varchar" { + strArr = append(strArr, column.DataType.String+"(255)") + } else { + strArr = append(strArr, column.DataType.String) + } + } else { + strArr = append(strArr, column.DataType.String+"("+strconv.Itoa(int(column.MaxLength.Int64))+")") + } + + if column.ColumnDefault.String != "" { + strArr = append(strArr, "DEFAULT '"+column.ColumnDefault.String+"'") + } + + if column.IsNullable.String == "NO" { + strArr = append(strArr, "NOT NULL") + } + + if column.ColumnComment.String != "" { + strArr = append(strArr, "COMMENT '"+column.ColumnComment.String+"'") + } + + if column.Extra.String != "" { + strArr = append(strArr, column.Extra.String) + } + + return strings.Join(strArr, " ") +} + +func getIndexStr(index Index) string { + var strArr []string + + if "PRIMARY" == index.KeyName.String { + strArr = append(strArr, index.KeyName.String) + strArr = append(strArr, "KEY") + strArr = append(strArr, "(`"+index.ColumnName.String+"`)") + } else { + if 0 == index.NonUnique.Int64 { + strArr = append(strArr, "Unique") + strArr = append(strArr, index.KeyName.String) + strArr = append(strArr, "(`"+index.ColumnName.String+"`)") + } else { + strArr = append(strArr, "Index") + strArr = append(strArr, index.KeyName.String) + strArr = append(strArr, "(`"+index.ColumnName.String+"`)") + } + } + + return strings.Join(strArr, " ") +} + +func getDataType(fieldType string, fieldMap map[string]string) string { + var DataType string + + dataTypeVal, dataTypeOk := fieldMap["type"] + if dataTypeOk { + DataType = dataTypeVal + } else { + if "Int" == fieldType { + DataType = "int" + } + if "String" == fieldType { + DataType = "varchar" + } + if "Bool" == fieldType { + DataType = "tinyint" + } + if "Time" == fieldType { + DataType = "datetime" + } + if "Float" == fieldType { + DataType = "float" + } + } + + return DataType +} + +func getMaxLength(DataType string, fieldMap map[string]string) int { + var MaxLength int + + maxLengthVal, maxLengthOk := fieldMap["size"] + if maxLengthOk { + num, _ := strconv.Atoi(maxLengthVal) + MaxLength = num + } else { + MaxLength = 0 + if "varchar" == DataType { + MaxLength = 255 + } + } + + return MaxLength +} + +func getNullAble(fieldMap map[string]string) string { + var IsNullable string + + _, primaryOk := fieldMap["primary"] + if primaryOk { + IsNullable = "NO" + } else { + _, ok := fieldMap["not null"] + if ok { + IsNullable = "NO" + } else { + IsNullable = "YES" + } + } + + return IsNullable +} + +func getComment(fieldMap map[string]string) string { + commentVal, commentIs := fieldMap["comment"] + if commentIs { + return commentVal + } + + return "" +} + +func getExtra(fieldMap map[string]string) string { + _, commentIs := fieldMap["auto_increment"] + if commentIs { + return "auto_increment" + } + + return "" +} + +func getDefaultVal(fieldMap map[string]string) string { + defaultVal, defaultIs := fieldMap["default"] + if defaultIs { + return defaultVal + } + + return "" +} diff --git a/migrator/migrator.go b/migrator/migrator.go new file mode 100644 index 0000000..4d4cdfe --- /dev/null +++ b/migrator/migrator.go @@ -0,0 +1,90 @@ +package migrator + +import ( + "github.com/tangpanqing/aorm/executor" + "github.com/tangpanqing/aorm/helper" + "github.com/tangpanqing/aorm/migrate_mysql" + "github.com/tangpanqing/aorm/model" + "reflect" + "strings" +) + +type Migrator struct { + //数据库操作连接 + LinkCommon model.LinkCommon + + //驱动名字 + driverName string + + //表属性 + opinionList []model.OpinionItem +} + +func (mi *Migrator) Driver(driverName string) *Migrator { + mi.driverName = driverName + return mi +} + +func (mi *Migrator) Opinion(key string, val string) *Migrator { + if key == "COMMENT" { + val = "'" + val + "'" + } + + mi.opinionList = append(mi.opinionList, model.OpinionItem{Key: key, Val: val}) + + return mi +} + +//ShowCreateTable 获取创建表的ddl +func (mi *Migrator) ShowCreateTable(tableName string) string { + if mi.driverName == "mysql" { + me := migrate_mysql.MigrateExecutor{ + DriverName: mi.driverName, + OpinionList: mi.opinionList, + Ex: &executor.Executor{ + LinkCommon: mi.LinkCommon, + }, + } + return me.ShowCreateTable(tableName) + } + return "" +} + +// AutoMigrate 迁移数据库结构,需要输入数据库名,表名自动获取 +func (mi *Migrator) AutoMigrate(dest interface{}) { + typeOf := reflect.TypeOf(dest) + arr := strings.Split(typeOf.String(), ".") + tableName := helper.UnderLine(arr[len(arr)-1]) + + mi.migrateCommon(tableName, typeOf) +} + +// Migrate 自动迁移数据库结构,需要输入数据库名,表名 +func (mi *Migrator) Migrate(tableName string, dest interface{}) { + typeOf := reflect.TypeOf(dest) + mi.migrateCommon(tableName, typeOf) +} + +func (mi *Migrator) migrateCommon(tableName string, typeOf reflect.Type) { + if mi.driverName == "mysql" { + me := migrate_mysql.MigrateExecutor{ + DriverName: mi.driverName, + OpinionList: mi.opinionList, + Ex: &executor.Executor{ + LinkCommon: mi.LinkCommon, + }, + } + me.MigrateCommon(tableName, typeOf) + } + + if mi.driverName == "sqlite3" { + //cr := migrate_sqlite3.MigrateExecutor{ + // Ex: ex, + //} + //cr.MigrateCommon(tableName, typeOf) + } +} + +func (mi *Migrator) GetOpinionList() []model.OpinionItem { + return mi.opinionList +} diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..75d2b71 --- /dev/null +++ b/model/model.go @@ -0,0 +1,15 @@ +package model + +import "database/sql" + +type LinkCommon interface { + Exec(query string, args ...interface{}) (sql.Result, error) + Prepare(query string) (*sql.Stmt, error) + Query(query string, args ...interface{}) (*sql.Rows, error) + QueryRow(query string, args ...interface{}) *sql.Row +} + +type OpinionItem struct { + Key string + Val string +} diff --git a/test/aorm_test.go b/test/aorm_test.go index c4c4482..60ca7be 100644 --- a/test/aorm_test.go +++ b/test/aorm_test.go @@ -6,6 +6,7 @@ import ( _ "github.com/mattn/go-sqlite3" "github.com/tangpanqing/aorm" "github.com/tangpanqing/aorm/executor" + "github.com/tangpanqing/aorm/helper" "github.com/tangpanqing/aorm/null" "testing" "time" @@ -55,31 +56,30 @@ type PersonWithArticleCount struct { } func TestAll(t *testing.T) { - sqlite3Content, sqlite3Err := aorm.Open("sqlite3", "test.db") - if sqlite3Err != nil { - panic(sqlite3Err) - } - - //username := "root" - //password := "root" - //hostname := "localhost" - //port := "3306" - //dbname := "database_name" - // - //mysqlContent, mysqlErr := aorm.Open("mysql", username+":"+password+"@tcp("+hostname+":"+port+")/"+dbname+"?charset=utf8mb4&parseTime=True&loc=Local") - //if mysqlErr != nil { - // panic(mysqlErr) + //sqlite3Content, sqlite3Err := aorm.Open("sqlite3", "test.db") + //if sqlite3Err != nil { + // panic(sqlite3Err) //} + username := "root" + password := "root" + hostname := "localhost" + port := "3306" + dbname := "database_name" + + mysqlContent, mysqlErr := aorm.Open("mysql", username+":"+password+"@tcp("+hostname+":"+port+")/"+dbname+"?charset=utf8mb4&parseTime=True&loc=Local") + if mysqlErr != nil { + panic(mysqlErr) + } + dbList := make([]aorm.DbContent, 0) - dbList = append(dbList, sqlite3Content) - //dbList = append(dbList, mysqlContent) + //dbList = append(dbList, sqlite3Content) + dbList = append(dbList, mysqlContent) for i := 0; i < len(dbList); i++ { dbItem := dbList[i] testMigrate(dbItem.DriverName, dbItem.DbLink) - break testShowCreateTable(dbItem.DriverName, dbItem.DbLink) @@ -156,15 +156,15 @@ func testMysqlConnect() *sql.DB { func testMigrate(name string, db *sql.DB) { //AutoMigrate - aorm.Use(db).Driver(name).Opinion("ENGINE", "InnoDB").Opinion("COMMENT", "人员表").AutoMigrate(&Person{}) - aorm.Use(db).Driver(name).Opinion("ENGINE", "InnoDB").Opinion("COMMENT", "文章").AutoMigrate(&Article{}) + aorm.Migrator(db).Driver(name).Opinion("ENGINE", "InnoDB").Opinion("COMMENT", "人员表").AutoMigrate(&Person{}) + aorm.Migrator(db).Driver(name).Opinion("ENGINE", "InnoDB").Opinion("COMMENT", "文章").AutoMigrate(&Article{}) //Migrate - aorm.Use(db).Driver(name).Opinion("ENGINE", "InnoDB").Opinion("COMMENT", "人员表").Migrate("person_1", &Person{}) + aorm.Migrator(db).Driver(name).Opinion("ENGINE", "InnoDB").Opinion("COMMENT", "人员表").Migrate("person_1", &Person{}) } func testShowCreateTable(name string, db *sql.DB) { - aorm.Use(db).Driver(name).ShowCreateTable("person") + aorm.Migrator(db).Driver(name).ShowCreateTable("person") } func testInsert(name string, db *sql.DB) int64 { @@ -589,9 +589,9 @@ func testHelper(name string, db *sql.DB) { where2 = append(where2, executor.WhereItem{Field: "p.age", Opt: executor.In, Val: []int{18, 20}}) err := aorm.Use(db).Debug(false). Table("article o"). - LeftJoin("person p", aorm.Ul("p.id=o.personId")). + LeftJoin("person p", helper.Ul("p.id=o.personId")). Select("o.*"). - Select(aorm.Ul("p.name as personName")). + Select(helper.Ul("p.name as personName")). WhereArr(where2). GetMany(&list2) if err != nil {