Gnok is in Limited Availability: a preview with no uptime commitment. Don’t store sensitive data; data may be deleted.
Skip to main content

Release notes

Changes that can affect how your SQL, data loads or connections behave, newest first. Gnok updates continuously; there is nothing to install.

October 17, 2026​

Functions refuse results larger than 256 MiB​

What changed. Functions whose result size is set by an argument now check that size before building the result. When one result value would be larger than 256 MiB, or the results of one call (one batch of rows) would add up to more than 1 GiB, the statement fails with SQLSTATE 54000 (program_limit_exceeded):

SELECT array_repeat(1, 9223372036854775807);
-- ARRAY_REPEAT: the result value would be 73786976294838206456 bytes, over the limit of
-- 268435456 bytes per value (GNOK_MAX_VALUE_BYTES) [code: VALUE_TOO_LARGE]

Why. Before this change, such a call kept allocating until the process serving the query ran out of memory. The statement failed with an internal error, and other queries running on the same compute failed with it.

Who is affected. Statements that ask these functions for very large results:

  • ARRAY_REPEAT and GENERATE_SERIES (as a function returning an array)
  • REPEAT, LPAD and RPAD
  • REPLACE and REGEXP_REPLACE
  • SPRINTF width and precision
  • H3_CELL_TO_CHILDREN and H3_GRID_DISK

Results under the limits are unchanged. Arrow and Flight SQL clients see the error with gRPC status OUT_OF_RANGE and the x-gnok-sqlstate: 54000 trailer; PostgreSQL clients see SQLSTATE 54000.

October 16, 2026​

CREATE TABLE ... AS uses the column list you declare​

What changed. In CREATE TABLE name (column type, ...) AS <query>, the declared column names and types now define the new table. Each query column is converted to the declared type in order:

CREATE TABLE prices (symbol VARCHAR, price DECIMAL(10, 2)) AS
VALUES ('GNK', 12.5), ('ACME', 3);

SELECT prices.symbol, prices.price FROM prices; -- columns symbol, price DECIMAL(10,2)

Why. Before this change Gnok ignored the list. The table silently got the query's own column names and types instead, for example column0/column1 for AS VALUES or col_0 for an unnamed expression, so a later prices.symbol failed with Column not found and the declared types were lost.

Who is affected. Statements that give CREATE TABLE ... AS a column list. Without a list, the query's names and types are used as before. Some statements that used to succeed now fail with an error instead of being silently ignored:

  • a list whose number of columns differs from the query's;
  • column options in the list (NOT NULL, DEFAULT, PRIMARY KEY and other constraints). Create the table first, then INSERT ... SELECT;
  • a type CREATE TABLE does not support, such as INT UNSIGNED;
  • a query whose own column names repeat. Give the query's columns distinct aliases.

DDL through JDBC executeUpdate reports 0 rows​

executeUpdate (Flight SQL DoPut) now returns the number of rows a statement changed: an INSERT of three rows returns 3, and UPDATE, DELETE, MERGE and COPY INTO return the rows they changed or loaded. DDL such as CREATE TABLE and DROP TABLE returns 0. Before this change every statement returned 1.

October 15, 2026​

COPY INTO needs the unit of numbers loaded into TIMESTAMP and DATE columns​

What changed. COPY INTO no longer guesses what a number means when it loads into a TIMESTAMP or DATE column. Add the EPOCH_UNIT and DATE_INTEGER_FORMAT file-format options to say what the numbers count:

-- ClickBench hits: EventTime is epoch seconds, EventDate is days since 1970-01-01
COPY INTO hits
FROM '@stage/hits/'
FILE_FORMAT = (TYPE = PARQUET, EPOCH_UNIT = 'seconds', DATE_INTEGER_FORMAT = 'EPOCH_DAYS');

Why. The same number means different instants: 1372636800 is 2013-07-01 counted in seconds but 1970-01-16 counted in milliseconds, and 20130701 is 2013-07-01 written as YYYYMMDD but a day in the year 57086 counted as days. Before this change, numbers loaded into a TIMESTAMP column from Parquet or JSON were taken as microseconds, so a file of epoch seconds loaded as dates in January 1970 without any error. A load now either uses the unit you give or stops.

Who is affected. Loads where a TIMESTAMP column is fed from an integer, decimal or floating-point source column, or from number text in CSV or JSON, and loads where a DATE column is fed from integers. Date and time text such as 2013-07-01 12:00:00 loads as before. Without the option the load fails with an error that names the column and shows one of its values read each way, for example:

column 'EventTime': the source values are numbers (UInt32), and loading numbers into a TIMESTAMP needs the unit they count since 1970-01-01. For example, 1372636800 is 2013-07-01 00:00:00 UTC in seconds, 1970-01-16 21:17:16 UTC in milliseconds, 1970-01-01 00:22:52 UTC in microseconds or 1970-01-01 00:00:01 UTC in nanoseconds. Add EPOCH_UNIT = 'seconds', 'milliseconds', 'microseconds' or 'nanoseconds' to FILE_FORMAT (no unit is assumed)

Pick the reading that matches your data and add that option. The error only shows the readings; nothing is loaded until you choose.

If you loaded numeric timestamps earlier. Numbers loaded into a TIMESTAMP column from Parquet or JSON before this change were stored as microseconds. If they were seconds or milliseconds, the column holds dates in the first weeks of January 1970:

SELECT MIN(ts), MAX(ts) FROM events;

Reload those files with the right EPOCH_UNIT to correct them.

Also in this release​

  • CSV timestamps keep their fractional seconds. 2013-07-01 12:00:00.123456 loads as exactly that into a TIMESTAMP column; earlier, CSV loads dropped the fraction.
  • Out-of-range values fail instead of wrapping. A value a column cannot hold is an error naming the value, never a wrapped, clamped or NULL timestamp. ON_ERROR applies to it as to any other bad value.
  • TO_TIMESTAMP(n, unit). Converts a number with an explicit unit in SQL, for example TO_TIMESTAMP(1372636800000, 'milliseconds'). TRY_TO_TIMESTAMP returns NULL for a value out of range. See Functions.