package sqlite import "strings" // SQLiteToCanonicalTypes maps SQLite type names to canonical types. // SQLite has type affinity rules; this maps common type names including // MySQL/PostgreSQL types that users write in SQLite schemas. var SQLiteToCanonicalTypes = map[string]string{ // Integer affinity "integer": "int", "int": "int", "tinyint": "int8", "smallint": "int16", "mediumint": "int", "bigint": "int64", "unsigned big int": "uint64", "int2": "int16", "int8": "int64", // Real affinity "real": "float64", "double": "float64", "double precision": "float64", "float": "float32", // Numeric affinity "numeric": "decimal", "decimal": "decimal", // Boolean (stored as integer in SQLite) "boolean": "bool", "bool": "bool", // Date/time (stored as text in SQLite) "date": "date", "datetime": "timestamp", "timestamp": "timestamp", // Text affinity "text": "string", "varchar": "string", "char": "string", "character": "string", "varying character": "string", "nchar": "string", "nvarchar": "string", "clob": "text", // Blob affinity "blob": "bytea", } // CanonicalToSQLiteAffinity maps type names to SQLite type affinity names. // Accepts both Go canonical names ("int", "string") and SQL canonical names // ("integer", "varchar") so the writer handles input from any reader. // The five SQLite type affinities are TEXT, INTEGER, REAL, NUMERIC, BLOB. var CanonicalToSQLiteAffinity = map[string]string{ // INTEGER affinity — Go canonical "int": "INTEGER", "int8": "INTEGER", "int16": "INTEGER", "int32": "INTEGER", "int64": "INTEGER", "uint": "INTEGER", "uint8": "INTEGER", "uint16": "INTEGER", "uint32": "INTEGER", "uint64": "INTEGER", "bool": "INTEGER", // INTEGER affinity — SQL canonical "integer": "INTEGER", "smallint": "INTEGER", "bigint": "INTEGER", "serial": "INTEGER", "smallserial": "INTEGER", "bigserial": "INTEGER", "boolean": "INTEGER", "tinyint": "INTEGER", "mediumint": "INTEGER", // REAL affinity — Go canonical "float32": "REAL", "float64": "REAL", // REAL affinity — SQL canonical "real": "REAL", "float": "REAL", "double": "REAL", "double precision": "REAL", // NUMERIC affinity "decimal": "NUMERIC", "numeric": "NUMERIC", "money": "NUMERIC", "smallmoney": "NUMERIC", // BLOB affinity "bytea": "BLOB", "blob": "BLOB", // TEXT affinity — Go canonical "string": "TEXT", "text": "TEXT", // TEXT affinity — SQL canonical "varchar": "TEXT", "char": "TEXT", "nvarchar": "TEXT", "nchar": "TEXT", "citext": "TEXT", "date": "TEXT", "time": "TEXT", "timetz": "TEXT", "timestamp": "TEXT", "timestamptz": "TEXT", "datetime": "TEXT", "uuid": "TEXT", "json": "TEXT", "jsonb": "TEXT", "xml": "TEXT", "inet": "TEXT", "cidr": "TEXT", "macaddr": "TEXT", } // ConvertSQLiteToCanonical converts a SQLite type name to the canonical type. // Strips dimension parameters (e.g. VARCHAR(255) → string) and handles // SQLite's flexible affinity rules. Defaults to "string" for unknown types. func ConvertSQLiteToCanonical(sqliteType string) string { base := strings.ToUpper(strings.TrimSpace(sqliteType)) if idx := strings.Index(base, "("); idx >= 0 { base = strings.TrimSpace(base[:idx]) } lower := strings.ToLower(base) if canonical, ok := SQLiteToCanonicalTypes[lower]; ok { return canonical } // Prefix match for types like "VARYING CHARACTER(255)" for key, canonical := range SQLiteToCanonicalTypes { if strings.HasPrefix(lower, key) { return canonical } } return "string" } // ConvertCanonicalToSQLite converts a canonical type (or any SQL type) to its // SQLite type affinity. Defaults to TEXT for unrecognised types. func ConvertCanonicalToSQLite(canonicalType string) string { normalized := strings.ToLower(strings.TrimSpace(canonicalType)) if idx := strings.Index(normalized, "("); idx >= 0 { normalized = strings.TrimSpace(normalized[:idx]) } normalized = strings.TrimSuffix(normalized, "[]") if affinity, ok := CanonicalToSQLiteAffinity[normalized]; ok { return affinity } return "TEXT" }