feat(sqlite): add SQLite type mapping and conversion functions

* Implement SQLiteToCanonicalTypes for type mapping
* Add ConvertSQLiteToCanonical and ConvertCanonicalToSQLite functions
* Update mapDataType to utilize new conversion logic
This commit is contained in:
2026-05-19 19:26:09 +02:00
parent 80fb49bc5e
commit cb735f0754
6 changed files with 430 additions and 147 deletions
+94 -50
View File
@@ -2,32 +2,73 @@ package mssql
import "strings"
// CanonicalToMSSQLTypes maps canonical types to MSSQL types
// CanonicalToMSSQLTypes maps canonical types to MSSQL types.
// Accepts both Go canonical names ("int", "string") and SQL canonical names
// ("integer", "varchar") so the writer handles input from any reader.
var CanonicalToMSSQLTypes = map[string]string{
"bool": "BIT",
"int8": "TINYINT",
"int16": "SMALLINT",
"int": "INT",
"int32": "INT",
"int64": "BIGINT",
"uint": "BIGINT",
"uint8": "SMALLINT",
"uint16": "INT",
"uint32": "BIGINT",
"uint64": "BIGINT",
"float32": "REAL",
"float64": "FLOAT",
"decimal": "NUMERIC",
"string": "NVARCHAR(255)",
"text": "NVARCHAR(MAX)",
// Boolean — Go and SQL canonical
"bool": "BIT",
"boolean": "BIT",
// Integer — Go canonical
"int8": "TINYINT",
"int16": "SMALLINT",
"int": "INT",
"int32": "INT",
"int64": "BIGINT",
"uint": "BIGINT",
"uint8": "TINYINT",
"uint16": "SMALLINT",
"uint32": "BIGINT",
"uint64": "BIGINT",
// Integer — SQL canonical (serial types map to base integer; IDENTITY is set via AutoIncrement)
"integer": "INT",
"smallint": "SMALLINT",
"bigint": "BIGINT",
"tinyint": "TINYINT",
"serial": "INT",
"smallserial": "SMALLINT",
"bigserial": "BIGINT",
// Float — Go canonical
"float32": "REAL",
"float64": "FLOAT",
// Float — SQL canonical
"real": "REAL",
"double precision": "FLOAT",
"double": "FLOAT",
// Decimal/numeric
"decimal": "NUMERIC",
"numeric": "NUMERIC",
"money": "MONEY",
// String — Go canonical
"string": "NVARCHAR(255)",
"text": "NVARCHAR(MAX)",
// String — SQL canonical
"varchar": "NVARCHAR(255)",
"char": "NCHAR",
"nvarchar": "NVARCHAR(255)",
"nchar": "NCHAR",
"citext": "NVARCHAR(MAX)",
// Date/time
"date": "DATE",
"time": "TIME",
"timetz": "DATETIMEOFFSET",
"timestamp": "DATETIME2",
"timestamptz": "DATETIMEOFFSET",
"uuid": "UNIQUEIDENTIFIER",
"json": "NVARCHAR(MAX)",
"jsonb": "NVARCHAR(MAX)",
"bytea": "VARBINARY(MAX)",
"datetime": "DATETIME2",
"interval": "NVARCHAR(50)",
// UUID
"uuid": "UNIQUEIDENTIFIER",
// JSON — MSSQL has no native JSON type; stored as NVARCHAR(MAX)
"json": "NVARCHAR(MAX)",
"jsonb": "NVARCHAR(MAX)",
// Binary
"bytea": "VARBINARY(MAX)",
"blob": "VARBINARY(MAX)",
// Network/geo types — no MSSQL native equivalent
"xml": "XML",
"inet": "NVARCHAR(45)",
"cidr": "NVARCHAR(43)",
"macaddr": "NVARCHAR(17)",
}
// MSSQLToCanonicalTypes maps MSSQL types to canonical types
@@ -68,47 +109,50 @@ var MSSQLToCanonicalTypes = map[string]string{
"geometry": "string",
}
// ConvertCanonicalToMSSQL converts a canonical type to MSSQL type
// MSSQLTypeSynonyms maps MSSQL type aliases to their canonical MSSQL name.
var MSSQLTypeSynonyms = map[string]string{
"integer": "int",
"dec": "decimal",
"float(n)": "float",
}
// NormalizeMSSQLType maps an MSSQL base type (no dimension parameters) to its
// canonical MSSQL form. Unknown types are returned as-is (lowercased).
func NormalizeMSSQLType(baseType string) string {
lower := strings.ToLower(strings.TrimSpace(baseType))
if canonical, ok := MSSQLTypeSynonyms[lower]; ok {
return canonical
}
return lower
}
// ConvertCanonicalToMSSQL converts a canonical type (Go or SQL) to an MSSQL type.
// Strips dimension parameters before lookup. Defaults to NVARCHAR(255) for unknown types.
func ConvertCanonicalToMSSQL(canonicalType string) string {
// Check direct mapping
if mssqlType, exists := CanonicalToMSSQLTypes[strings.ToLower(canonicalType)]; exists {
base := strings.ToLower(strings.TrimSpace(canonicalType))
if idx := strings.Index(base, "("); idx >= 0 {
base = strings.TrimSpace(base[:idx])
}
base = strings.TrimSuffix(base, "[]")
if mssqlType, exists := CanonicalToMSSQLTypes[base]; exists {
return mssqlType
}
// Try to find by prefix
lowerType := strings.ToLower(canonicalType)
for canonical, mssql := range CanonicalToMSSQLTypes {
if strings.HasPrefix(lowerType, canonical) {
return mssql
}
}
// Default to NVARCHAR
return "NVARCHAR(255)"
}
// ConvertMSSQLToCanonical converts an MSSQL type to canonical type
// ConvertMSSQLToCanonical converts an MSSQL type to the canonical type.
// Strips dimension parameters before lookup. Defaults to "string" for unknown types.
func ConvertMSSQLToCanonical(mssqlType string) string {
// Extract base type (remove parentheses and parameters)
baseType := mssqlType
if idx := strings.Index(baseType, "("); idx != -1 {
baseType = baseType[:idx]
base := strings.ToLower(strings.TrimSpace(mssqlType))
if idx := strings.Index(base, "("); idx >= 0 {
base = strings.TrimSpace(base[:idx])
}
baseType = strings.TrimSpace(baseType)
// Check direct mapping
if canonicalType, exists := MSSQLToCanonicalTypes[strings.ToLower(baseType)]; exists {
if canonicalType, exists := MSSQLToCanonicalTypes[base]; exists {
return canonicalType
}
// Try to find by prefix
lowerType := strings.ToLower(baseType)
for mssql, canonical := range MSSQLToCanonicalTypes {
if strings.HasPrefix(lowerType, mssql) {
return canonical
}
}
// Default to string
return "string"
}