diff --git a/ddlmod.go b/ddlmod.go index d00f3ef..1464f9c 100644 --- a/ddlmod.go +++ b/ddlmod.go @@ -20,9 +20,9 @@ var ( checkRegexp = regexp.MustCompile(`^(?i)CHECK[\s]*\(`) constraintRegexp = regexp.MustCompile(fmt.Sprintf(`^(?i)CONSTRAINT\s+%[1]s[\w\d_]+%[1]s[\s]+`, sqliteColumnQuote)) separatorRegexp = regexp.MustCompile(fmt.Sprintf("[%v]", sqliteSeparator)) - columnRegexp = regexp.MustCompile(fmt.Sprintf(`^[%v]?([\w\d]+)[%v]?\s+([\w\(\)\d]+)(.*)$`, sqliteSeparator, sqliteSeparator)) + columnRegexp = regexp.MustCompile(fmt.Sprintf(`^[%v]?([\w\d]+)[%v]?\s+(\w+(?:\([^)]*\))?)(.*)$`, sqliteSeparator, sqliteSeparator)) defaultValueRegexp = regexp.MustCompile(`(?i) DEFAULT \(?(.+)?\)?( |COLLATE|GENERATED|$)`) - regRealDataType = regexp.MustCompile(`[^\d](\d+)[^\d]?`) + typeSizeRegexp = regexp.MustCompile(`\((\d+)\s*(?:,\s*(\d+))?\)$`) ) type ddl struct { @@ -160,12 +160,17 @@ func parseDDL(strs ...string) (*ddl, error) { } } - // data type length - matches := regRealDataType.FindAllStringSubmatch(columnType.DataTypeValue.String, -1) - if len(matches) == 1 && len(matches[0]) == 2 { - size, _ := strconv.Atoi(matches[0][1]) - columnType.LengthValue = sql.NullInt64{Valid: true, Int64: int64(size)} - columnType.DataTypeValue.String = strings.TrimSuffix(columnType.DataTypeValue.String, matches[0][0]) + // data type length / precision, e.g. varchar(10), decimal(10,2) + if sizeMatches := typeSizeRegexp.FindStringSubmatch(columnType.DataTypeValue.String); sizeMatches != nil { + size, _ := strconv.Atoi(sizeMatches[1]) + if sizeMatches[2] != "" { + scale, _ := strconv.Atoi(sizeMatches[2]) + columnType.DecimalSizeValue = sql.NullInt64{Valid: true, Int64: int64(size)} + columnType.ScaleValue = sql.NullInt64{Valid: true, Int64: int64(scale)} + } else { + columnType.LengthValue = sql.NullInt64{Valid: true, Int64: int64(size)} + } + columnType.DataTypeValue.String = strings.TrimSuffix(columnType.DataTypeValue.String, sizeMatches[0]) } result.columns = append(result.columns, columnType) diff --git a/ddlmod_test.go b/ddlmod_test.go index 7d4e1a2..5a0a733 100644 --- a/ddlmod_test.go +++ b/ddlmod_test.go @@ -475,3 +475,30 @@ func TestGetColumns(t *testing.T) { }) } } + +func TestParseDDL_TypePrecision(t *testing.T) { + d, err := parseDDL("CREATE TABLE `t` (`p` decimal(10,2), `s` decimal(10, 2), `v` varchar(25))") + if err != nil { + t.Fatal(err) + } + for _, c := range d.columns { + switch c.NameValue.String { + case "p", "s": + if c.DataTypeValue.String != "decimal" { + t.Errorf("%s: DataType = %q, want decimal", c.NameValue.String, c.DataTypeValue.String) + } + precision, scale, ok := c.DecimalSize() + if !ok || precision != 10 || scale != 2 { + t.Errorf("%s: DecimalSize = (%d,%d,%v), want (10,2,true)", c.NameValue.String, precision, scale, ok) + } + case "v": + if length, ok := c.Length(); !ok || length != 25 { + t.Errorf("v: Length = (%d,%v), want (25,true)", length, ok) + } + } + } + // the full column type is preserved for the first form + if ct, _ := d.columns[0].ColumnType(); ct != "decimal(10,2)" { + t.Errorf("ColumnType = %q, want decimal(10,2)", ct) + } +}