Work in Progress: This page is under development. Use the feedback button on the bottom right to help us improve it.

Data Types

Laminar supports a rich set of SQL data types for stream processing. Examples use the sample data.

Primitive Types

Booleans

BOOLEAN

Values: TRUE, FALSE, NULL

SELECT
  order_id,
  status,
  status = 'completed' as is_completed,
  amount > 100 as is_high_value
FROM orders
order_idstatusis_completedis_high_value
ord_1completedtruetrue
ord_2completedtruefalse
ord_3pendingfalsetrue
ord_4cancelledfalsefalse
ord_5completedtruetrue

Integers

TypeRangeUse Case
INT / INTEGER-2B to 2BCounts, IDs, small numbers
BIGINT-9Q to 9QLarge counts, timestamps as ms
INT UNSIGNED0 to 4BAlways-positive integers
BIGINT UNSIGNED0 to 18QVery large positive numbers
SELECT
  metric_id,
  CAST(value as INTEGER) as value_int,
  CAST(value as INTEGER) * 2 as doubled,
  CAST(value as INTEGER) / 2 as halved
FROM metrics
WHERE name = 'requests'
metric_idvalue_intdoubledhalved
m812502500625

Note: Integer division truncates decimals. Cast to DOUBLE for decimal results.


Floating Point

TypePrecisionUse Case
FLOAT / REAL~7 digitsGeneral decimals
DOUBLE~15 digitsScientific, financial
DECIMAL(p, s)ExactMoney, precise calculations
SELECT
  order_id,
  amount,
  (amount * 0.08)::DECIMAL(10, 2) as tax,
  (amount * 1.08)::DECIMAL(10, 2) as total
FROM orders
WHERE status = 'completed'
order_idamounttaxtotal
ord_1150.0012.00162.00
ord_275.506.0481.54
ord_5300.0024.00324.00
ord_6125.0010.00135.00
ord_789.997.2097.19

Text

VARCHAR    -- Variable-length string (most common)
TEXT       -- Alias for VARCHAR
STRING     -- Alias for VARCHAR
CHAR       -- Fixed-length (rarely needed)

All text types are UTF-8 encoded with no length limit.

SELECT
  log_id,
  UPPER(level) as level_upper,
  LOWER(service) as service_lower,
  LENGTH(message) as message_length
FROM logs
log_idlevel_upperservice_lowermessage_length
l1INFOauth47
l2ERRORpayment54
l3WARNapi54
l4INFOorders42
l5ERRORinventory40
l6INFOcache29

Timestamps

TIMESTAMP

Represents a point in time with nanosecond precision.

SELECT
  order_id,
  timestamp,
  DATE_TRUNC('hour', timestamp) as order_hour,
  EXTRACT(MINUTE FROM timestamp) as minute
FROM orders
WHERE status = 'completed'
order_idtimestamporder_hourminute
ord_12024-01-15 10:00:152024-01-15 10:00:000
ord_22024-01-15 10:00:352024-01-15 10:00:000
ord_52024-01-15 10:02:202024-01-15 10:00:002
ord_62024-01-15 10:02:552024-01-15 10:00:002
ord_72024-01-15 10:03:302024-01-15 10:00:003

Binary

BYTEA

Raw byte sequences for binary data.

SELECT
  log_id,
  message,
  MD5(message) as message_hash
FROM logs
log_idmessagemessage_hash
l1User login successful user_id=u1 ip=192.168.1.1a1b2c3...
l2Payment failed order_id=ord_3 error=insufficient_fundsd4e5f6...

Composite Types

Arrays

Group multiple values of the same type.

Declaration:

VARCHAR[]           -- Array of strings
INT[]               -- Array of integers
DOUBLE[]            -- Array of floats

Creating arrays:

SELECT
  customer_id,
  ARRAY_AGG(order_id) as order_ids,
  ARRAY_AGG(amount) as amounts
FROM orders
WHERE customer_id = 'c1'
GROUP BY customer_id
customer_idorder_idsamounts
c1[ord_1, ord_3, ord_7][150.00, 200.00, 89.99]

Array Operations

Access elements (1-indexed):

SELECT
  customer_id,
  ARRAY_AGG(order_id) as orders,
  (ARRAY_AGG(order_id))[1] as first_order
FROM orders
GROUP BY customer_id
customer_idordersfirst_order
c1[ord_1, ord_3, ord_7]ord_1
c2[ord_2, ord_5]ord_2

Get array length:

SELECT
  customer_id,
  ARRAY_AGG(order_id) as orders,
  ARRAY_LENGTH(ARRAY_AGG(order_id)) as order_count
FROM orders
GROUP BY customer_id
customer_idordersorder_count
c1[ord_1, ord_3, ord_7]3
c2[ord_2, ord_5]2

Structs

Combine related fields into a single column.

Declaration:

STRUCT<
  street VARCHAR,
  city VARCHAR,
  zip VARCHAR
>

Access struct fields:

SELECT
  order_id,
  metadata.source,
  metadata.channel
FROM orders_with_metadata
order_idsourcechannel
ord_1weborganic
ord_2mobilepaid

Type Casting

Convert between types with CAST or :: syntax.

SELECT
  order_id,
  amount,
  CAST(amount as INTEGER) as amount_int,
  amount::VARCHAR as amount_str,
  timestamp::DATE as order_date
FROM orders
order_idamountamount_intamount_strorder_date
ord_1150.00150150.002024-01-15
ord_275.507575.502024-01-15
ord_3200.00200200.002024-01-15

NULL Handling

All types are nullable. Handle NULLs explicitly.

SELECT
  order_id,
  customer_id,
  COALESCE(region, 'unknown') as region,
  amount IS NOT NULL as has_amount
FROM orders
order_idcustomer_idregionhas_amount
ord_1c1us-eastTRUE
ord_2c2us-westTRUE
ord_3c1us-eastTRUE

Type Inference

Laminar infers types from your connectors:

  • JSON format: Types inferred from schema definition
  • Avro/Protobuf: Types derived from schema
  • Parquet/Iceberg: Types from table metadata

When types don't match, Laminar attempts automatic coercion. If coercion fails, you'll get a validation error before the pipeline starts.

Best Practices

  1. Use BIGINT for timestamps when storing as milliseconds
  2. Use DECIMAL for money to avoid floating-point errors
  3. Prefer VARCHAR over CHAR for text
  4. Use arrays for variable-length lists of the same type
  5. Use structs for fixed, known fields