Skip to content

Commit

Permalink
Add support for database field definition (easysoft#25)
Browse files Browse the repository at this point in the history
* 除整型外,其余字段range属性使用双引号包括

* 字符串类型、时间类型生成与默认配置相符

*  field_test.yaml为示例文件
  • Loading branch information
hind3ight authored Dec 6, 2021
1 parent 33f9bcd commit 39e41f4
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 4 deletions.
39 changes: 39 additions & 0 deletions demo/field_test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
CREATE TABLE `field_test` (
`Bit` bit(64) NULL DEFAULT NULL,
`TinyInt` tinyint NULL DEFAULT NULL,
`SmallInt` smallint NULL DEFAULT NULL,
`MediumInt` mediumint NULL DEFAULT NULL,
`GeometryCollection` GEOMETRYCOLLECTION NULL,
`Int` int NULL DEFAULT NULL,
`BigInt` bigint NULL DEFAULT NULL,
`Float(M,D)` float NULL DEFAULT NULL,
`Double(M,D)` double NULL DEFAULT NULL,
`Decimal(M,D)` decimal(10,0) NULL DEFAULT NULL,
`Date` date NULL DEFAULT NULL,
`DateTime` datetime NULL DEFAULT NULL,
`TimeStamp` datetime NULL DEFAULT NULL,
`Time` time NULL DEFAULT NULL,
`Year` year NULL DEFAULT NULL,
`Char` char(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`VarChar(M)` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`Binary(M)` binary(255) NULL DEFAULT NULL,
`TinyText` tinytext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,
`Text` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
`MediumText` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,
`LongText` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,
`TinyBlob` tinyblob NULL,
`Blob` blob NULL,
`MediumBlob` mediumblob NULL,
`LongBlob` longblob NULL,
`Enum` enum('1','2') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`Set` set('set1','set2') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '',
`Geometry` geometry NULL,
`Point` point NULL,
`LineString` linestring NULL,
`Polygon` polygon NULL,
`MultiPoint` multipoint NULL,
`MultiLineString` multilinestring NULL,
`MultiPolygon` multipolygon NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;
169 changes: 165 additions & 4 deletions src/action/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"gopkg.in/yaml.v3"
"io/ioutil"
"regexp"
"strconv"
"strings"
"time"
)
Expand Down Expand Up @@ -45,7 +46,7 @@ func ParseSql(file string, out string) {
for tableName, statement := range statementMap {
createStr := statement

columns := getColumnsFromCreateStatement(createStr)
columns, types := getColumnsFromCreateStatement2(createStr)

def := model.DefSimple{}
def.Init(tableName, "automated export", "", "1.0")
Expand All @@ -64,15 +65,24 @@ func ParseSql(file string, out string) {
field.From = "keys.yaml"
field.Use = fmt.Sprintf("%s_%s{:1}", fkInfo[0], fkInfo[1])
} else {
field.Range = "-"
if types[col] == `"DATE"` || types[col] == `"TIME"` || types[col] == `"YEAR"` || types[col] == `"DATETIME"` || types[col] == `"TIMESTAMP"` {
field.Range = strconv.Quote("20210821 000000:60")
field.Type = "timestamp"
field.Format = strconv.Quote("YY/MM/DD hh:mm:ss")
} else if types[col] == `"CHAR"` || types[col] == `"VARCHAR"` || types[col] == `"TINYTEXT"` || types[col] == `"TEXT"` || types[col] == `"MEDIUMTEXT"` || types[col] == `"LONGTEXT"` {
field.Range = types[col]
field.Loop = "'3'" // default value of loop
field.Loopfix = "_"
} else {
field.Range = types[col]
}
}

def.Fields = append(def.Fields, field)
}

bytes, _ := yaml.Marshal(&def)
content := strings.ReplaceAll(string(bytes), "'-'", "\"\"")

content := strings.ReplaceAll(string(bytes), "'", "")
if out != "" {
out = fileUtils.AddSepIfNeeded(out)
outFile := out + tableName + ".yaml"
Expand Down Expand Up @@ -151,3 +161,154 @@ func getColumnsFromCreateStatement(sent string) []string {

return fieldLines
}

func getColumnsFromCreateStatement2(sent string) (fieldLines []string, fieldInfo map[string]string) {
fieldLines = make([]string, 0)
re := regexp.MustCompile("(?iU)\\s*(\\S+)\\s.*\n")
arr := re.FindAllStringSubmatch(string(sent), -1)
fieldInfo = map[string]string{}
for _, item := range arr {
line := strings.ToLower(item[0])
if !strings.Contains(line, " table ") && !strings.Contains(line, " key ") {
fieldTmp := item[1]
field := strings.ReplaceAll(fieldTmp, "`", "")
fieldInfo[field] = parseFieldInfo(strings.ToUpper(fieldTmp), item[0])
fieldLines = append(fieldLines, field)
}
}

return fieldLines, fieldInfo
}

func parseFieldInfo(fieldTmp, fieldTypeInfo string) (ran string) {
var ret []string
isUnsigned := false
fieldTypeInfo = strings.ToUpper(fieldTypeInfo)
if strings.Contains(fieldTypeInfo, "UNSIGNED") { // judge unsigned
isUnsigned = true
}

myExp := regexp.MustCompile(fieldTmp + `\s([A-Z]+)\(([^,]*),?([^,]*)\)`)
ret = myExp.FindStringSubmatch(fieldTypeInfo)
if ret != nil {
ran = judgeFieldType(ret[1], ret[2], isUnsigned)
} else {
fieldType := strings.Split(strings.Fields(fieldTypeInfo)[1], "(")[0]
ran = judgeFieldType(fieldType, "", isUnsigned)
}

return ran
}

func judgeFieldType(fieldType, num string, isUnsigned bool) (ran string) {
switch fieldType {
// integer
case "BIT":
if isUnsigned {
ran = "0-255"
} else {
ran = "-128-127"
}
case "TINYINT":
if num == "1" {
ran = "0-1"
} else if isUnsigned {
ran = "0-255"
} else {
ran = "-128-127"
}
case "SMALLINT":
if isUnsigned {
ran = "0-65535"
} else {
ran = "-32768-32767"
}
case "MEDIUMINT":
if isUnsigned {
ran = "0-65535"
} else {
ran = "-32768-32767"
}
case "INT", "INTEGER":
if isUnsigned {
ran = "[0,2^32-1]"
} else {
ran = "[-2^31,2^31-1]"
}
case "BIGINT":
if isUnsigned {
ran = "[0,2^64-1]"
} else {
ran = "[-2^63 ,2^63 -1]"
}
// floating-point
case "FLOAT":
ran = `"FLOAT"`
case "DOUBLE":
ran = `"DOUBLE"`
// fixed-point
case "DECIMAL":
ran = `"DECIMAL"`
// character string
case "CHAR":
ran = `"CHAR"`
case "VARCHAR":
ran = `"VARCHAR"`
case "TINYTEXT":
ran = `"TINYTEXT"`
case "TEXT":
ran = `"TEXT"`
case "MEDIUMTEXT":
ran = `"MEDIUMTEXT"`
case "LONGTEXT":
ran = `"LONGTEXT"`
// binary data
case "TINYBLOB":
ran = `"TINYBLOB"`
case "BLOB":
ran = `"BLOB"`
case "MEDIUMBLOB":
ran = `"MEDIUMBLOB"`
case "LONGBLOB":
ran = `"LONGBLOB"`
case "BINARY":
ran = "BINARY"
case "VARBINARY":
ran = "VARBINARY"
// Date and time type
case "DATE":
ran = `"DATE"`
case "TIME":
ran = `"TIME"`
case "YEAR":
ran = `"YEAR"`
case "DATETIME":
ran = `"DATETIME"`
case "TIMESTAMP":
ran = `"TIMESTAMP"`
// other type
case "ENUM":
ran = `"ENUM"`
case "SET":
ran = `"SET"`
case "GEOMETRY":
ran = `"GEOMETRY"`
case "POINT":
ran = `"POINT"`
case "LINESTRING":
ran = `"LINESTRING"`
case "POLYGON":
ran = `"POLYGON"`
case "MULTIPOINT":
ran = `"MULTIPOINT"`
case "MULTILINESTRING":
ran = `"MULTILINESTRING"`
case "MULTIPOLYGON":
ran = `"MULTIPOLYGON"`
case "GEOMETRYCOLLECTION":
ran = `"GEOMETRYCOLLECTION"`
default:
}

return ran
}

0 comments on commit 39e41f4

Please sign in to comment.