Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for database field definition #25

Merged
merged 6 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}