--- title: "Data types" slug: "dev-database-reference-data-types" description: "Explore VAST DataBase 5.5 column types, their Arrow, Trino, Spark, and Python SDK mappings, and precision nuances for optimal data handling." updated: 2026-10-30T18:18:46Z published: 2026-10-30T18:18:46Z canonical: "docs.vastdata.com/dev-database-reference-data-types" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.vastdata.com/llms.txt > Use this file to discover all available pages before exploring further. # Data types *Applies to VAST Cluster 5.5. Examples use the VAST DataBase Python SDK 2.1.0.* This page shows which column types VAST DataBase supports in VAST Cluster 5.5, what each one is called in Arrow, Trino, Spark and the Python SDK, and where precision can change between them. ## Type mapping | VAST DataBase | Arrow | Trino | Spark | Python SDK (PyArrow) | | --- | --- | --- | --- | --- | | UINT8, UINT16, UINT32, UINT64 | UINT8, UINT16, UINT32, UINT64 | n/a | n/a | `pa.uint8()` … `pa.uint64()` | | INT8, INT16, INT32, INT64 | INT8, INT16, INT32, INT64 | TINYINT, SMALLINT, INTEGER, BIGINT | TINYINT, SMALLINT, INTEGER, BIGINT | `pa.int8()` … `pa.int64()` | | BOOL | BOOL | BOOLEAN | BOOLEAN | `pa.bool_()` | | FLOAT32, FLOAT64 | FLOAT, DOUBLE | REAL, DOUBLE | REAL, DOUBLE | `pa.float32()`, `pa.float64()` | | STRING | STRING | VARCHAR | STRING | `pa.string()` (or `pa.utf8()`) | | BINARY | BINARY | VARBINARY | BINARY | `pa.binary()` | | DECIMAL128 | DECIMAL128 | DECIMAL | DECIMAL | `pa.decimal128(precision, scale)` | | DATE32 | DATE32 | DATE | DATE | `pa.date32()` | | TIMESTAMP | TIMESTAMP | TIMESTAMP | TIMESTAMP | `pa.timestamp(unit)`, with unit `"s"`, `"ms"`, `"us"` or `"ns"` | | TIMESTAMP WITH TZ | TIMESTAMP | TIMESTAMP WITH TIMEZONE | TIMESTAMP | `pa.timestamp(unit, tz=...)` | | TIME32 | TIME32 | TIME | n/a | `pa.time32("s")`, `pa.time32("ms")` | | TIME64 | TIME64 | TIME | n/a | `pa.time64("us")`, `pa.time64("ns")` | | MAP | MAP | MAP | MapType | `pa.map_(key_type, item_type)` | | ARRAY | LIST | ARRAY | ArrayType | `pa.list_(value_type)` | | ROW | STRUCT | ROW | StructType | `pa.struct([...])` | | UUID | UUID | UUID | CHAR(16) | Not available in SDK 2.1.0 (see [below](/develop/docs/dev-database-reference-data-types#types-the-sdk-cant-use)) | | VECTOR | LIST of INT or FLOAT | n/a | n/a | A [fixed-size list](/develop/docs/dev-database-reference-data-types#fixed-size-lists-and-vectors) | See [Supported Data Types](/docs-5-5/docs/supported-data-types). The SDK also supports **float16** (`pa.float16()`, half precision) since SDK 2.0.6 (SDK changelog). The cluster accepts it. ## Engine differences | Engine | Difference | | --- | --- | | VAST Query Engine | No time-zone types: a `TIMESTAMP WITH TIME ZONE` column can be created and written, but selecting it fails with `Unsupported column type`, and `TIME WITH TIME ZONE` is refused at `CREATE TABLE`. Use `TIMESTAMP` in UTC. See [data types in SQL](/develop/docs/dev-database-reference-sql-data-types). | | VAST Query Engine | No `map` type. `struct` and `array` are supported. See [5.5.0 release notes](/docs-5-5/docs/vast-cluster-5-5-0-release-notes) and [VAST Query Engine](/docs-5-5/docs/vast-query-engine). | | VAST Query Engine | The vector type is written `vector(<element-type>, <dimension>)`, for example `vector(float, 128)`. See [SQL reference](/develop/docs/dev-database-reference-sql-create-table#vector-indexed-tables) and [Vector index](/docs-5-5/docs/vector-database-index). | | Trino | No unsigned integers, and no vector type. Views can't use nested types. See [Supported Data Types](/docs-5-5/docs/supported-data-types) and [Trino connector](/docs-5-5/docs/installing-and-configuring-the-vast-connector-for-trino). | | Spark | No unsigned integers, `TIME` or vector type. All nested types (struct, array, map) are supported. See [Supported Data Types](/docs-5-5/docs/supported-data-types) and [Spark managed application](/docs-5-5/docs/spark-managed-cnode-application). | Nested columns (`list`, `map`, `struct`) can't be partition columns or sort columns. For filtering on nested columns, see [pushdowns](/develop/docs/dev-database-reference-pushdowns#python-sdk). ## Precision caveats **Timestamps.** Check the precision of any type that has one. For example, a `timestamp` in a Parquet file can show as `timestamp(3)` in Trino, because of a Trino default, while VAST DataBase processes it as `timestamp(6)` (see [Supported Data Types](/docs-5-5/docs/supported-data-types)). From the SDK, the unit you give in `pa.timestamp()` is the unit the column keeps: a `pa.timestamp("ns")` column comes back as `timestamp[ns]`. A timezone is kept too: `pa.timestamp("us", tz="Europe/Lisbon")` comes back unchanged. **Spark has no unsigned or time types.** A UINT or TIME column has no Spark type. If Spark has to read the table, use signed integers and timestamps. **Decimal filters in the Python SDK.** SDK 2.1.0 turns a decimal literal in a predicate into a Python `float` before it scales it to an integer, and drops the remainder. So the value the cluster compares against can be one unit of the scale lower than the one you wrote. For example, on a `decimal128(10, 2)` column, `t["price"] == 0.29` matches the row with `0.28`. Don't rely on exact decimal comparisons in a pushed-down predicate. Push down a range that's wider by one unit of the scale on each side, then filter exactly in Arrow. Ibis also rejects a `decimal.Decimal` literal against a decimal column ("not comparable"), so pass a `float`. **Float literals** are sent with the column's own type, so `t["f32"] == 0.1` on a `float32` column matches a stored `0.1`. ## Fixed-size lists and vectors A vector column is a PyArrow fixed-size list whose element field is **not nullable**: `pa.list_(pa.field("item", pa.float32(), nullable=False), dim)`. The SDK has supported fixed-size lists of numbers since 1.3.11 (SDK changelog). | Rule | | --- | | Element types: `uint8`-`uint64`, `int8`-`int64`, `float16`, `float32`, `float64`, `decimal128`, `date32`, `timestamp`, `time32`, `time64` | | Not allowed as elements: `string`, `binary`, `bool`, lists, maps and structs | | The element field must be non-nullable. Otherwise the cluster rejects the table with `NotSupportedSchema`, message `FIXED_SIZE_LIST nullable sub-type (float) is not supported, only non-nullable is supported` | | The list size must be at least 1. Size 0 is rejected with `TabularInvalidColumnTypeParam`. | To build a vector index on the column, see [VectorIndexSpec](/develop/docs/dev-database-reference-sdk#vector-index). The size of a single cell is limited; see [limits](/develop/docs/dev-database-reference-limits#sizes). ## Types the SDK can't use If a column type isn't supported, `create_table()` and `add_column()` raise `vastdb.errors.NotSupportedSchema` ([error reference](/develop/docs/dev-database-troubleshooting-errors#vastdberrorsnotsupportedschema)). These were all rejected: | PyArrow type | Rejected by | Use instead | | --- | --- | --- | | `pa.large_string()`, `pa.string_view()` | Cluster: `Unsupported column type ...` | `pa.string()` | | `pa.large_list(...)` | Cluster | `pa.list_(...)` | | `pa.date64()` | Cluster | `pa.date32()` | | `pa.decimal256(...)` | Cluster | `pa.decimal128(...)`, up to precision 38 | | `pa.dictionary(...)` | Cluster | The dictionary's value type. Decode with `.cast()` or `pc.dictionary_decode()` before you insert. | | `pa.duration(...)` | Cluster | An integer column | | `pa.null()` | Cluster: `The field named '<name>' has an unsupported Arrow type 'null'` | Give the column a real type | | `pa.binary(n)` (fixed-size binary) | SDK: `Ibis does not support the schema ...` | `pa.binary()` | | `pa.uuid()` | SDK: `Ibis does not support the schema ...` | `pa.binary()` or `pa.string()` | | `pa.month_day_nano_interval()` | SDK: `Ibis does not support the schema ...` | Separate integer columns | "SDK" means the error is raised before any request is sent, because Ibis can't represent the type. The SDK needs Ibis to build predicates. The cluster has a fixed-size binary type: [limits](/develop/docs/dev-database-reference-limits#sizes) gives its cell size. But SDK 2.1.0 can't create or open a table with one (SDK tests, `test_unsupported_types`). ## Example: a table with several types This example creates a table with a mix of types, prints the column types the cluster reports, then shows the decimal caveat and its workaround. It uses the connection environment variables from the [quickstart](/develop/docs/dev-database-quickstart#2-connect). ``` import decimal import os import pyarrow as pa import pyarrow.compute as pc import vastdb session = vastdb.connect() BUCKET = os.environ["VASTDB_BUCKET"] columns = pa.schema([ ("id", pa.int64()), ("reading", pa.float16()), ("price", pa.decimal128(10, 2)), ("day", pa.date32()), ("taken_at", pa.timestamp("us", tz="UTC")), ("tags", pa.list_(pa.utf8())), ("embedding", pa.list_(pa.field("item", pa.float32(), nullable=False), 3)), ("location", pa.struct([("lat", pa.float64()), ("lon", pa.float64())])), ("attrs", pa.map_(pa.utf8(), pa.utf8())), ]) with session.transaction() as tx: schema = tx.bucket(BUCKET).create_schema("ref_data_types", fail_if_exists=False) table = schema.create_table("samples", columns, fail_if_exists=False) for field in table.columns(): print(f"{field.name}: {field.type}") ``` ``` id: int64 reading: halffloat price: decimal128(10, 2) day: date32[day] taken_at: timestamp[us, tz=UTC] tags: list embedding: fixed_size_list[3] location: struct attrs: map ``` Insert two rows, then filter for a price of `0.29`: ``` import datetime as dt rows = pa.table({ "id": [1, 2], "reading": pa.array([0.5, 1.5], pa.float16()), "price": [decimal.Decimal("0.28"), decimal.Decimal("0.29")], "day": [dt.date(2026, 1, 1), dt.date(2026, 1, 2)], "taken_at": [dt.datetime(2026, 1, 1, 12, tzinfo=dt.timezone.utc), dt.datetime(2026, 1, 2, 12, tzinfo=dt.timezone.utc)], "tags": [["a"], []], "embedding": [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]], "location": [{"lat": 38.7, "lon": -9.1}, {"lat": 59.9, "lon": 10.7}], "attrs": [[("colour", "red")], []], }, schema=columns) with session.transaction() as tx: table = tx.bucket(BUCKET).schema("ref_data_types").table("samples") table.insert(rows) result = table.select(columns=["id", "price"], predicate=table["price"] == 0.29).read_all() print(result.sort_by("id").to_pylist()) ``` ``` [{'id': 1, 'price': Decimal('0.28')}] ``` The row that comes back has price `0.28`, not `0.29`. To filter on an exact decimal, push down a range one unit of the scale (here `0.01`) wider on each side, then compare exactly in Arrow: ``` with session.transaction() as tx: table = tx.bucket(BUCKET).schema("ref_data_types").table("samples") wide = table.select(columns=["id", "price"], predicate=table["price"].between(0.28, 0.30)).read_all() wanted = pa.scalar(decimal.Decimal("0.29"), pa.decimal128(10, 2)) exact = wide.filter(pc.equal(wide["price"], wanted)) print(exact.to_pylist()) ``` ``` [{'id': 2, 'price': Decimal('0.29')}] ``` Clean up: ``` with session.transaction() as tx: schema = tx.bucket(BUCKET).schema("ref_data_types") schema.table("samples").drop() schema.drop() print("Dropped") ``` ``` Dropped ```