Type mapping reference

This page covers how identifiers are converted from PostgreSQL to Snowflake on mirror targets, and how PostgreSQL data types map to Iceberg.

Name mapping

Schema, table, and column names from the source PostgreSQL database are converted to uppercase in the target database. For example, the PostgreSQL column created_at is written as CREATED_AT in the target table. Replicating Postgres tables with the same name in different case isn’t supported.

Type mapping

PostgreSQL types are classified as either supported or unsupported. Supported types are replicated directly (native) or cast to text/binary. Unsupported types are blocked when you add a table to the publication.

Native types

These types have direct Iceberg equivalents and are replicated without conversion:

PostgreSQL typeIceberg typeNotes
booleanboolean
smallint / int2int
integer / int4int
bigint / int8long
real / float4float
double precision / float8double
numeric(p,s) where p ≤ 38, s ≤ 38decimal(p,s)
numeric (unbounded)doubleValues exceeding the float8 range overflow to +/-Infinity
numeric(p,s) where p > 38 or s > 38doubleValues exceeding the float8 range overflow to +/-Infinity
datedate
time (without time zone)time
time with time zone / timetztimeUTC-normalized
timestamp (without time zone)timestamp
timestamp with time zonetimestamptz
intervalstructStored as struct with months, days, microseconds
textstring
varchar(n)string
char(n) / bpcharstring
byteabinary
uuiduuid
Arrays of native typeslist<T>For example, int[] becomes list<int>. Multidimensional values are clamped to NULL.
Composite types (all native fields)struct<...>All fields must be native types

Fallback types

Types not listed above are cast to string or binary when written to Iceberg. This includes types like json, jsonb, hstore, and vector.

Some fallback types have restrictions:

PostgreSQL typeIceberg typeNotes
geometrybinaryWKB encoding. Top-level only. Requires pg_lake_spatial extension.
int4range, int8range, and other range typesstringTop-level only
int4multirange and other multirange typesstringTop-level only

PostGIS geometry values are stored as WKB in a BINARY column rather than a Snowflake GEOMETRY. Cast at query time with TO_GEOMETRY if you need Snowflake geospatial functions.

Unsupported types

These types are blocked when you add a table to the publication:

PostgreSQL typeReasonWorkaround
map types (pg_map)Not supported in CDCUse JSONB for key-value data
Table types (non-composite)Not valid for Iceberg columnsNone
Nested geometry (geometry[], geometry in composites)Not supported in IcebergUse top-level geometry only
Geometry without pg_lake_spatialCDC worker needs spatial supportCREATE EXTENSION pg_lake_spatial CASCADE
Nested range/multirange typesNot supported in IcebergUse top-level range types only

Domains are transparently resolved to their base types. A domain over an unsupported type is also blocked.

Nested type handling

Arrays and composite types have special rules depending on their element or field types:

Arrays:

Element typeSupported
Supported typeYes
Unsupported typeNo (blocked)
GeometryNo (blocked)
Range/multirangeNo (blocked)
uuidNo (blocked)

Composite types:

Field typesSupported
All fields supportedYes
Any field unsupportedNo (blocked)
Contains geometry fieldNo (blocked)
Contains range fieldNo (blocked)
Contains uuid fieldNo (blocked)

uuid is an exception to the “supported type → yes” rule: it’s supported as a standalone column but is blocked when nested inside an array or composite type. Tables with nested UUID columns are rejected at publication time.

Value clamping

Even for supported types, certain special values can’t be represented in Iceberg. These values are silently clamped at write time.

Temporal values (date, timestamp, timestamptz):

Infinity and out-of-range temporal values are clamped to the nearest Iceberg boundary:

PostgreSQL valueClamped value
date 'infinity'9999-12-31
date '-infinity'4713-01-01 BC
timestamp 'infinity'9999-12-31 23:59:59.999999
timestamp '-infinity'0001-01-01 00:00:00
timestamptz 'infinity'9999-12-31 23:59:59.999999 UTC
timestamptz '-infinity'0001-01-01 00:00:00 UTC

Numeric NaN:

NaN in bounded numeric columns (for example, numeric(20,5)) is clamped to NULL because Iceberg’s decimal type doesn’t support NaN.

Numeric Infinity (unbounded):

Unbounded numeric and numeric(p,s) with p > 38 or s > 38 are converted to double precision. IEEE 754 Infinity and -Infinity are valid double values and are preserved (not clamped).

Multidimensional arrays:

PostgreSQL allows multidimensional array values (for example, ARRAY[[1,2],[3,4]]), but Iceberg’s list type is single-dimensional. Multidimensional array values are clamped to NULL at write time. A column declared as int[] that contains a 1D value (for example, ARRAY[1,2,3]) is stored normally; only values with more than one dimension are nullified.

Oversize string and binary values:

Snowflake imposes maximum sizes on string and binary columns (16 MiB for strings, 8 MiB for binary). Values that exceed these limits are clamped at write time. The cap is inclusive: a value at exactly the limit is stored verbatim; only values that exceed it are clamped.

PostgreSQL typeAction when over the cap
text, varchar, bpcharTruncated at a UTF-8 character boundary to the 16 MiB (16,777,216-byte) cap. A multibyte character is never split, so the result may land a byte or two under the cap.
byteaByte-truncated to the 8 MiB (8,388,608-byte) cap.
jsonb, jsonSet to NULL. Truncating the serialized text would produce invalid JSON.
hstore, citext, and other string-backed typesSet to NULL. There is no safe truncation point for these types.
String or binary leaf inside an array or compositeClamped per-leaf to the 16 MiB or 8 MiB cap, same as a top-level column.
array or composite (aggregate)Set to NULL when the entire serialized container exceeds 128 MiB, independent of the per-leaf cap above.