The COPY ... TO statement writes the result of a query (or the contents of a table) to files. It is the only Chalk SQL statement that produces output outside of the query response itself; all other statements are read-only.

Examples

-- Export a query result to a single Parquet file
COPY (
    SELECT user_id, sum(amount) AS total
    FROM "my_bigquery.my_dataset.transactions"
    GROUP BY user_id
) TO 's3://my-bucket/exports/user_totals.parquet';

-- Export a table to a directory of CSV files
COPY "my_postgres.public.users" TO 's3://my-bucket/exports/users/' (FORMAT 'csv');

-- Export selected columns only
COPY "my_postgres.public.users" (user_id, email) TO 'gs://my-bucket/users.parquet';

-- Hive-partitioned Parquet output
COPY (SELECT * FROM "my_bigquery.my_dataset.transactions")
TO 's3://my-bucket/exports/transactions/'
(FORMAT 'parquet', PARTITION_BY (country, year));

-- Write an Iceberg table with a partition spec
COPY (SELECT * FROM "my_bigquery.my_dataset.transactions")
TO 's3://my-bucket/warehouse/transactions'
(FORMAT 'iceberg', PARTITION_BY (bucket(16, user_id), day(created_at)));

Syntax

COPY ( select_statement ) TO 'uri' [ ( option [, ...] ) ];
COPY "catalog.schema.table" [ (column [, ...]) ] TO 'uri' [ ( option [, ...] ) ];

The destination uri determines where files are written; the storage backend is selected from the URI scheme (for example a local path, s3://, or gs://). A URI ending in .parquet or .csv targets a single file, while a directory-style URI (trailing /) writes one or more files with generated names beneath it.

Options

OptionDescription
FORMAT'parquet' (default), 'csv', or 'iceberg'. When omitted, the format is inferred from the destination file extension, falling back to Parquet.
PARTITION_BYPartitions the output. For Parquet and CSV, accepts column names and produces Hive-style partitioned directories. For Iceberg, additionally accepts the partition transforms bucket(N, col), truncate(W, col), year(col), month(col), day(col), and hour(col).
WRITE_BLOOM_FILTERParquet only: write bloom filters for the output files.
BLOOM_FILTER_FALSE_POSITIVE_RATIOParquet only: bloom filter false-positive ratio in (0, 1); defaults to 0.01. Setting this implies WRITE_BLOOM_FILTER true.

Iceberg output

With FORMAT 'iceberg', the destination URI names the Iceberg table root (a directory, not a file). Chalk SQL writes the Parquet data files and commits the Iceberg metadata (manifests and a new snapshot) beneath that root, creating the table on first write. PARTITION_BY entries define the table’s partition spec; a bare column name is an identity transform.

Limitations

  • COPY ... FROM (loading data) is not supported — Chalk SQL is a read-only interface over your data sources.
  • FORMAT 'delta' is not supported.
  • Bloom filter options require FORMAT 'parquet' and cannot be combined with PARTITION_BY.