Skip to main content
Version: 1.16.0

Type matrix

What Migrate and PlanMigration generate for each Go type, on each engine.

This page is generated from the type mapper itself, so it cannot drift from what the code does. A hand-written version was wrong about integer widths for as long as it existed.

Go typePostgreSQLMySQLMariaDBSQLiteSQL ServerOracle
stringTEXTVARCHAR(255)VARCHAR(255)TEXTNVARCHAR(255)VARCHAR2(255)
string with size=255VARCHAR(255)VARCHAR(255)VARCHAR(255)VARCHAR(255)NVARCHAR(255)VARCHAR2(255)
boolBOOLEANBOOLEANBOOLEANBOOLEANBITNUMBER(1)
int8 / int16SMALLINTSMALLINTSMALLINTSMALLINTSMALLINTNUMBER(5)
int32INTEGERINTEGERINTEGERINTEGERINTEGERNUMBER(10)
int / int64BIGINTBIGINTBIGINTBIGINTBIGINTNUMBER(19)
uint64BIGINTBIGINTBIGINTBIGINTBIGINTNUMBER(19)
float32REALREALREALREALREALBINARY_FLOAT
float64DOUBLE PRECISIONDOUBLEDOUBLEREALFLOAT(53)BINARY_DOUBLE
float64 with precision=18,scale=4DECIMAL(18,4)DECIMAL(18,4)DECIMAL(18,4)DECIMAL(18,4)DECIMAL(18,4)NUMBER(18,4)
time.TimeTIMESTAMPDATETIMEDATETIMEDATETIMEDATETIME2TIMESTAMP
[]byteBYTEABLOBBLOBBLOBVARBINARY(MAX)BLOB
time.DurationBIGINTBIGINTBIGINTBIGINTBIGINTNUMBER(19)
[16]byte (UUID-shaped, e.g. uuid.UUID)UUIDCHAR(36)CHAR(36)UUIDNCHAR(36)VARCHAR2(36)
integer primary keyBIGSERIAL PRIMARY KEYBIGINT AUTO_INCREMENT PRIMARY KEYBIGINT AUTO_INCREMENT PRIMARY KEYINTEGER PRIMARY KEY AUTOINCREMENTBIGINT IDENTITY(1,1) PRIMARY KEYNUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY
string primary keyVARCHAR(36) PRIMARY KEYVARCHAR(36) PRIMARY KEYVARCHAR(36) PRIMARY KEYVARCHAR(36) PRIMARY KEYNVARCHAR(36) PRIMARY KEYVARCHAR2(36) PRIMARY KEY
[]stringTEXT[]JSONJSONTEXTNVARCHAR(MAX)CLOB
[]int64BIGINT[]JSONJSONTEXTNVARCHAR(MAX)CLOB
map[string]anyJSONBJSONJSONTEXTNVARCHAR(MAX)CLOB
quark.Range[time.Time]TSTZRANGEJSONJSONTEXTNVARCHAR(MAX)CLOB
net.IPINETVARCHAR(45)VARCHAR(45)TEXTNVARCHAR(45)VARCHAR2(45)

Notes​

  • int / int64 — Go's int is 64-bit on every supported platform.
  • uint64 — Stored signed; values above 2⁶³−1 do not fit.
  • float64 with precision=18,scale=4 — Use this for money: binary floats cannot represent every decimal.
  • time.Duration — Stored as an integer count of nanoseconds.
  • [16]byte (UUID-shaped, e.g. uuid.UUID) — The value travels in text form through the type's own Valuer/Scanner. SQL Server's UNIQUEIDENTIFIER is not used: its driver scans it in the engine's mixed-endian byte order.
  • integer primary key — Auto-increment.
  • string primary key — For UUID/ULID keys the caller supplies.
  • []string — A raw slice of a scalar kind: a native array on PostgreSQL (the value travels as the array literal), JSON-backed elsewhere. quark.Array[T] remains the JSON-backed wrapper on every engine.
  • map[string]any — JSON-backed on every engine.
  • quark.Range[time.Time] — Range[int64] is INT8RANGE, Range[int32] INT4RANGE, Range[float64] NUMRANGE on PostgreSQL; JSON elsewhere.
  • net.IP — Bound and scanned as the textual address.

Integer width​

Integers map by the width of the Go type. They used to collapse onto a single INTEGER, which is four bytes on PostgreSQL, MySQL and SQL Server: an int64 past 2³¹ was rejected by those engines while looking fine on SQLite, whose INTEGER is dynamically sized. Auto-increment keys were narrow for the same reason and ran out at 2,147,483,647 rows.

If you have tables created before this changed, PlanMigration reports the widening as an ALTER COLUMN. Applying it is safe — widening loses no data — but on a large table the engine may rewrite it, so run it when a rewrite is acceptable rather than at deploy time.

Floating point​

REAL is single precision on PostgreSQL: about seven significant digits, where a float64 carries fifteen. SQLite's REAL is an 8-byte IEEE double and was never affected.

For money, use precision and scale and get a DECIMAL: no binary float represents every decimal fraction exactly.