Applies to VAST Cluster 5.5.
With the VAST connector for Trino, VAST DataBase appears in Trino as a catalog. You use ordinary Trino SQL to create tables, insert rows, query them and run transactions. This page covers what you need to know from the Trino side: how names map, which catalog properties matter, what VAST DataBase does for your queries, and how row and column security changes what you see.
Before you start
Whoever runs your Trino cluster needs to install the connector and add a VAST catalog. VAST ships a Trino server with the connector built in as a Docker image, vastdataorg/trino-vast on Docker Hub, with an image for each cluster version.
Admin task: send to your platform team. The install and configuration steps are in the KB: Installing and configuring the VAST connector for Trino. For the database, the endpoint, the access keys and the identity policy, see setup prerequisites.
What it needs, in short:
- A running Trino cluster with a low-latency, high-bandwidth network connection to the VAST cluster.
- A catalog file,
vast.properties, with the endpoint and an access key pair (see catalog properties). - Three JVM options in
jvm.config:
--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED
Version pairing
The connector is numbered to match Trino. On VAST Cluster 5.5, use Trino 478 with connector 478. The full table, including older clusters, is in version compatibility.
Catalog properties
This catalog file works with Trino 478. Trino names a catalog after its file, so vast.properties gives a catalog called vast.
connector.name=vast
endpoint={VAST_ENDPOINT}
region=us-east-1
access_key_id={VAST_ACCESS_KEY_ID}
secret_access_key={VAST_SECRET_ACCESS_KEY}
data_endpoints={VAST_DATA_ENDPOINTS}
num_of_splits=64
num_of_subsplits=10
vast.http-client.request-timeout=100h
vast.http-client.idle-timeout=290s
vast.http-client.max-connections-per-server=50
compression=zstd
With this file, the catalog runs DDL, INSERT, UPDATE, DELETE and SELECT against VAST Cluster 5.5. Two properties you may see in other examples don't work with Trino 478:
- No
vast.http-client.max-connections. Trino 478 refuses to start if a catalog file sets it:Defunct property 'vast.http-client.max-connections' (class [class HttpClientConfig]) cannot be configured. compression, notvast.compression. As a catalog property,vast.compressionis rejected (Configuration property 'vast.compression' was not used).vast.compressionis the name of the matching session property for a catalog calledvast.
| Property | Example value | What it is |
|---|---|---|
connector.name |
vast |
Selects the VAST connector. |
endpoint |
{VAST_ENDPOINT} |
The VAST DataBase endpoint. |
data_endpoints |
{VAST_DATA_ENDPOINTS} |
Not described on the Trino page. |
region |
us-east-1 |
Not described. |
access_key_id, secret_access_key |
Your key pair | The S3 access key pair the connector uses. |
num_of_splits |
64 (standalone example), 512 (managed app) | A preliminary tuning parameter. If the catalog file doesn't set it, connector 478 uses 1 split, so set it. |
num_of_subsplits |
10 (standalone example), 4 (managed app) | A preliminary tuning parameter. |
vast.http-client.request-timeout |
100h |
Request timeout. |
vast.http-client.idle-timeout |
290s |
Idle timeout. |
vast.http-client.max-connections-per-server |
50 | |
compression |
zstd |
Optional. Compresses data on the wire, using Zstandard. In a catalog file it's compression; Trino 478 rejects vast.compression there. |
The catalog holds one key pair. Unless end-user impersonation is set up (see row and column security), the cluster checks permissions against that key's user, not against the person running the query. Ask for a key whose identity policy allows only what your Trino users need. The actions are listed in setup prerequisites.
Session properties
Several catalog properties are also session properties, so you can change them for one session without editing the catalog file. With connector 478 these include num_of_splits, num_of_subsplits, data_endpoints, compression and the pushdown switches in what VAST DataBase does for your query. For a catalog called vast, their names start with vast.:
SET SESSION vast.num_of_splits = 128;
SET SESSION vast.num_of_subsplits = 4;
SHOW SESSION LIKE 'vast.num_of_s%';
SHOW SESSION then lists vast.num_of_splits with value 128 and default 64, and vast.num_of_subsplits with value 4 and default 10; the default is the catalog file's value. Run SHOW SESSION LIKE 'vast.%' to see every property your connector version has, with a description of each.
Names: databases, schemas and tables
VAST DataBase has databases, schemas and tables. Trino has catalogs, schemas and tables. The connector joins the database and schema into one Trino schema name, <database>/<schema>. Because of the /, quote it:
The examples on this page use a database (bucket) called vastdb. Create a schema in it:
CREATE SCHEMA vast."vastdb/schema1";
Then list what the catalog's key can see:
SHOW SCHEMAS FROM vast;
SHOW TABLES FROM vast."vastdb/schema1";
Schema
--------------------
information_schema
system_schema
vastdb/schema1
(3 rows)
Table
-------
(0 rows)
SHOW SCHEMAS FROM vast lists every database and schema the key can see, plus Trino's own information_schema and the connector's system_schema. In an interactive session, USE vast."vastdb/schema1"; saves typing the prefix.
Creating tables and writing data
DDL and DML work as in any Trino catalog. This is the verification sequence (see Installing and configuring the VAST connector for Trino):
CREATE TABLE vast."vastdb/schema1".cats (
weight BIGINT, name VARCHAR, attitude REAL, date DATE, time TIMESTAMP
);
DESCRIBE vast."vastdb/schema1".cats;
Column | Type | Extra | Comment
----------+--------------+-------+---------
weight | bigint | |
name | varchar | |
attitude | real | |
date | date | |
time | timestamp(3) | |
(5 rows)
TIMESTAMP with no precision became timestamp(3), Trino's default. For how Trino types map to VAST DataBase types, see data types.
Transactions work with START TRANSACTION and COMMIT:
START TRANSACTION;
INSERT INTO vast."vastdb/schema1".cats VALUES (12, 'happy', 18.7, date('2022-12-02'), now());
INSERT INTO vast."vastdb/schema1".cats VALUES (8, 'joy', 19.2, date('2022-12-02'), now());
COMMIT;
SELECT weight, name, attitude, date FROM vast."vastdb/schema1".cats ORDER BY weight;
weight | name | attitude | date
--------+-------+----------+------------
8 | joy | 19.2 | 2022-12-02
12 | happy | 18.7 | 2022-12-02
(2 rows)
Partitioned tables
Set partitioning when you create the table, with the partitioning table property. You can't add or change it later.
CREATE TABLE vast."vastdb/schema1".events (
event_id int,
event_time timestamp(6),
event_type varchar
)
WITH (
partitioning = ARRAY['day(event_time)', 'event_type']
);
SHOW CREATE TABLE vast."vastdb/schema1".events;
Create Table
---------------------------------------------------------
CREATE TABLE vast."vastdb/schema1".events (
event_id integer,
event_time timestamp(6),
event_type varchar
)
WITH (
partitioning = ARRAY['Day(event_time)','event_type']
)
(1 row)
This creates a partition for each combination of day and event type. The transforms (identity, bucket, truncate, year, month, day, hour) are listed in Database partitioning. What partitioning can be combined with is in limits.
Each partition shows up in the table's $partitions table. A transformed column is named with the transform as a suffix, so day(event_time) becomes event_time_day (and bucket(col2, 1024) would be col2_bucket):
INSERT INTO vast."vastdb/schema1".events VALUES
(1, TIMESTAMP '2026-09-16 10:00:00', 'click'),
(2, TIMESTAMP '2026-09-16 11:00:00', 'view'),
(3, TIMESTAMP '2026-09-17 10:00:00', 'click');
SELECT event_time_day, event_type FROM vast."vastdb/schema1"."events$partitions"
ORDER BY event_time_day, event_type;
event_time_day | event_type
----------------+------------
2026-09-16 | click
2026-09-16 | view
2026-09-17 | click
(3 rows)
To delete whole partitions, delete from $partitions, with the vast.allow_non_acid flag appended to the name:
DELETE FROM vast."vastdb/schema1"."events$partitions vast.allow_non_acid"
WHERE event_time_day = DATE '2026-09-16' AND event_type = 'click';
SELECT event_id, event_type FROM vast."vastdb/schema1".events ORDER BY event_id;
event_id | event_type
----------+------------
2 | view
3 | click
(2 rows)
As the flag says, this isn't ACID. Changing partitions while other writes go to the same table can leave the data in an indeterminate state. Don't run it while anything else writes to the table.
Sorted tables
You can make an existing table sorted with the sorted_by table property:
ALTER TABLE vast."vastdb/schema1".cats
SET PROPERTIES sorted_by = ARRAY['weight', 'name'];
SHOW CREATE TABLE vast."vastdb/schema1".cats;
Create Table
-------------------------------------------
CREATE TABLE vast."vastdb/schema1".cats (
weight bigint,
name varchar,
attitude real,
date date,
time timestamp(3)
)
WITH (
sorted_by = ARRAY['weight','name']
)
(1 row)
Once a table is sorted, you can't turn sorting off, change the sort columns or update their values. The other rules are in limits.
Views
You can create views from Trino. They're stored in the database. The examples are in the KB. In 5.5:
- View properties aren't supported.
- Nested data types aren't supported in views created from Trino.
- The
SECURITYclause ofCREATE VIEWisn't supported. - Queries in a view must use full table names.
- If the schema of the query changes when a view is redefined, its user-defined column names and comments are lost.
- Trino has no command that lists only views. Use a naming convention instead, such as a
_viewsuffix, andSHOW TABLES ... LIKE '%_view%'.
What VAST DataBase does for your query
When Trino scans a VAST table, VAST DataBase does part of the work: it returns only the columns the query needs, returns the count for a whole-table COUNT(*), and evaluates the filters the connector can hand it. With Trino 478:
| Pushed down to VAST DataBase | Filtered by Trino |
|---|---|
Comparisons, <>, ranges, BETWEEN, IN, IS NULL, on integers, decimals, doubles, booleans, strings, dates and timestamps |
LIKE with any other pattern: 'app%', '%ple', or a pattern with _ or an escape inside, such as '%a_a%' |
OR on one column; AND across columns |
OR across columns, unless you turn on complex_predicate_pushdown (below) |
LIKE '%substring%', a substring with no other wildcards |
A substring LIKE on a column that also has another filter, such as s LIKE '%nan%' AND s = 'banana' |
Comparing two columns, functions (upper(), substr()) and arithmetic (a + 1) |
The connector's session properties change what's pushed down. Their defaults in Trino 478:
| Session property | Default | Effect |
|---|---|---|
vast.match_substring_pushdown |
true |
Pushes down LIKE '%substring%'. |
vast.complex_predicate_pushdown |
false |
Pushes down an OR across columns, such as a = 1 OR b = 20. An OR of ANDs, such as (a = 1 AND b = 10) OR (a = 5 AND b = 20), still isn't pushed down. |
vast.expression_projection_pushdown |
false |
Pushes down computed columns (column expression projection). |
Set one for a session with SET SESSION vast.complex_predicate_pushdown = true;. Run SHOW SESSION LIKE 'vast.%' to see them all.
Trino does everything else on the rows that come back. In this query, for example, VAST DataBase evaluates both WHERE conditions and Trino computes the average:
SELECT avg(weight) AS avg_weight FROM vast."vastdb/schema1".cats WHERE weight > 5 AND attitude < 20;
avg_weight
------------
10.0
(1 row)
The full list of predicates is in pushdowns.
EXPLAIN
EXPLAIN works on VAST tables. It's the last check that the connector is set up:
EXPLAIN SELECT * FROM vast."vastdb/schema1".cats WHERE weight > 10 AND attitude < 10;
In the plan, the TableScan line lists each column's predicate as VAST DataBase will evaluate it, and a Filter or ScanFilterProject step above it is what Trino evaluates. For this query it holds SortedRangeSet[type=bigint, ranges=1, {(10,<max>)}] for weight and SortedRangeSet[type=real, ranges=1, {(<min>,10.0)}] for attitude (Trino 478, VAST Cluster 5.5). A condition that isn't listed there is evaluated by Trino. The plan also carries the table's internal handle, which changes from run to run.
The same holds for plain, sorted and partitioned tables: the pushed-down predicate is in the TableScan in each case. On a sorted table the scan also lists the sort columns (sorted_by@[Optional[[cust]]] for a table sorted on cust). A function such as upper(region) = 'EU' stays in Trino, as a filterPredicate in a ScanFilterProject step, while the plain conditions next to it are still pushed down. The plan doesn't show which partitions are skipped. More on pushdowns, including dynamic filtering for joins, is in pushdowns.
Partition pruning
On a partitioned table, the query engine skips partitions that can't match the query. It can also line up its splits with partition boundaries, so that a group-by, or a join between two tables partitioned the same way on the join key, needs no shuffle (Database partitioning). Filter on the partition columns to benefit.
Not available through Trino
The VAST connector for Trino doesn't support vector index-based search. Vector search runs through the VAST Query Engine; see Vector search.
Row and column security
Your platform team can add row and column security rules to identity policies. See Row and column security; security covers how they affect your queries. What you see in Trino:
- Column allow and deny. Denied columns aren't returned. With
ColumnAllow, only the listed columns are returned. This applies to queries, inserts and renames. It works on top-level columns only, not on fields inside nested columns. - Column masking. The column is returned, but its values are replaced by a SQL expression from the policy, for example
regexp_replace(my_col_email, '.*', '***'). The query doesn't fail. - Row filters. Rows that don't match the policy's filter are left out, as if the policy added a
WHEREclause. - Path-based row filters. If a table has the reserved
vastdb_s3_path_authcolumn, a row is returned only if the user may read every S3 path listed in it.
VAST DataBase returns the filters and masks, and the query engine applies them. Each filter and mask names the engines it applies to, for example "QueryEngine": "Trino". If a policy defines row filters or column masks for a user on a table, that user can query the table only through one of the engines named in the policy.
If a query names a denied column, it fails as if the column didn't exist: Column '<column>' cannot be resolved.
Warning: a catalog without the security flags below doesn't apply row filters. A catalog that uses an end user's own key, with no flags set, removes that user's denied column but returns every row, ignoring the user's row filter. If your rules include row filters, use a catalog with the flags set. A catalog with a service key and no flags returns whatever that key's user may see, to every Trino user.
What the catalog needs
For the rules to apply to the person running the query, the connector has to act on their behalf (end-user impersonation). Two things are needed.
The security flags in the catalog file. All three, with underscores:
enable_access_control=true
enable_row_column_security=true
enable_end_user_impersonation=true
Connector 478 rejects the names with hyphens, for example: Configuration property 'enable-access-control' was not used. Did you mean to use 'enable_access_control'?
Two actions for the catalog key's user. The identity policy of the user who owns the key in the catalog file (the service user) must allow s3:EndUserImpersonation and s3:TabularGetRowColumnSecurity. s3:Tabular* covers the second but not the first. Without them, every query on the catalog fails with 403 Forbidden - ACCESS DENIED, and the Trino server log has the cluster's reason:
- Without
s3:EndUserImpersonation, the query fails withfailed to execute request LIST_SCHEMA, path /vastdb not allowed; the log saysaction=EndUserImpersonation is not allowed (end_user=<trino-user>). - Without
s3:TabularGetRowColumnSecurity, it fails withfailed to execute request ROW_COLUMN_SECURITY, path /vastdb/schema1/<table> not allowed; the log saysaction=TabularGetRowColumnSecurity is not allowed (end_user=<trino-user>). s3:GetRowColumnSecuritydoesn't help: the error is the same as withouts3:TabularGetRowColumnSecurity.
If you set enable_access_control and enable_row_column_security without impersonation, the key's own user needs s3:TabularGetRowColumnSecurity; otherwise every query fails with the ROW_COLUMN_SECURITY error above.
Admin task: send to your platform team. See Enabling row and column security configurations.
Which user the rules apply to
The connector sends the Trino session user's name to the cluster as the end user. That name must be the login name of a VAST user; no mapping setting is needed. The cluster then applies that user's identity policy. If no VAST user has that name, the query fails with 403 Forbidden - ACCESS DENIED: failed to execute request LIST_SCHEMA, path /vastdb not allowed, and the server log says login_name=<trino-user> was not found. If your Trino cluster has authentication, the session user is the authenticated user.
With impersonation working:
- A user with a row filter gets only the matching rows, and a denied column is gone: naming it gives
Column '<column>' cannot be resolved. EXPLAINshows the row filter as a predicate in theTableScan, like any pushed-down filter, and leaves the denied column out.- Writes are checked as the end user too. An
INSERTof a row that doesn't match the user's row filter fails withAccess Denied: Cannot insert row that does not match a row filter, and an insert the user's policy doesn't allow fails with a 403Permission check failed. - The service user itself, as a Trino user, sees what its own policy allows.
Troubleshooting
A statement hangs instead of failing. If the catalog's endpoint is wrong or unreachable, the connector retries each request rather than failing, so statements appear to hang. With the default retry settings, a statement against an endpoint that refused connections was still retrying after 11 minutes; the server log shows retrying due to I/O error every second. Check endpoint first when a new catalog's queries never return.
One entry in data_endpoints is down. The query still completes with the right result. Requests to the dead entry are refused and retried, so the query only takes longer; the server log has Server refused connection lines naming that endpoint. Remove the entry, or ask your platform team which virtual IPs are current.
Trino as a managed application on the cluster
Trino can also run on the cluster's CNodes as a managed application. Connect to it with the Trino CLI on the coordinator's virtual IP, using the vast catalog:
./trino --server <coordinator-VIP>:8080 --catalog vast --schema <schema> --user <username>
Everything on this page applies to it too. Also:
- The application image is Trino 475. Use a Trino CLI of the same version.
- A cluster upgrade while the app runs can make queries fail. The app is fully working again once the upgrade completes.
- The app keeps running queries through a CNode failure, as long as one coordinator CNode and one worker CNode stay up.
Admin task: send to your platform team. Setting up the app is a DataEngine task: Trino managed CNode applications and Managed applications on clusters.
Clean up
DROP TABLE vast."vastdb/schema1".cats;
DROP TABLE vast."vastdb/schema1".events;
DROP SCHEMA vast."vastdb/schema1";