> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Полная справочная документация по модулю chdb_hook для Postgres

# Справочная документация по модулю chdb_hook

<h2 id="synopsis">
  Краткое описание
</h2>

```psql theme={null}
# LOAD 'chdb_hook';
LOAD

# CREATE TABLE times (
    id     INT NOT NULL,
    months INT NOT NULL,
    days   INT NOT NULL
);
CREATE TABLE

# COPY times FROM 's3://datasets-documentation/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv';
COPY 18
```

<h2 id="description">
  Описание
</h2>

Модуль chdb\_hook встраивается в команду PostgreSQL [COPY](#copy-overloading),
позволяя с помощью [chDB] копировать данные `TO` или `FROM` в любом из поддерживаемых
[форматов данных, предоставляемых chDB][formats], — в локальные файлы, бакеты [AWS S3],
[Google Cloud Storage] и другие хранилища. Он также встраивается в [CREATE TABLE], благодаря чему
таблица может получить описание своих столбцов и загрузить строки из любого из тех же
источников.

<h2 id="loading">
  Загрузка
</h2>

Загрузите chdb\_hook одним из следующих способов от имени суперпользователя. Выберите тот,
который лучше всего подходит для вашего сценария:

* Явно, командой [LOAD]; действует на протяжении сеанса:

  ```sql theme={null}
  LOAD 'chdb_hook';
  ```

  <Note>
    SQL Console в ClickHouse Cloud пока не поддерживает команду `LOAD 'chdb_hook'`,
    однако её можно выполнить через psql или любое другое подключение к базе данных.
    Либо обратитесь к своему представителю службы поддержки, чтобы её добавили
    в конфигурацию вашего сервиса Postgres, после чего её можно будет использовать в SQL Console.
  </Note>

* Для всех сеансов — с помощью настройки \[session\_preload\_libraries] в
  `postgresql.conf`:

  ```ini theme={null}
  session_preload_libraries = chdb_hook
  ```

  Или через [ALTER SYSTEM]:

  ```sql theme={null}
  ALTER SYSTEM SET session_preload_libraries = 'chdb_hook';
  ```

  Эту настройку можно задать и на уровне отдельной базы данных с помощью [ALTER DATABASE]:

  ```sql theme={null}
  ALTER DATABASE name SET session_preload_libraries = 'chdb_hook';
  ```

  Или для конкретных пользователей и групп с помощью [ALTER ROLE]:

  ```sql theme={null}
  ALTER ROLE name SET session_preload_libraries = 'chdb_hook';
  ```

* При запуске сервера — с помощью настройки \[shared\_preload\_libraries], чтобы расширение всегда
  было доступно во всех сеансах и базах данных:

  ```ini theme={null}
  shared_preload_libraries = chdb_hook
  ```

<Warning>
  Учтите, что загрузка chdb\_hook даёт пользователям с ролями `pg_read_server_files`
  или `pg_write_server_files` возможность выполнять `COPY` данных из файлов и в файлы на
  сервере Postgres, а также в облачное хранилище.
</Warning>

<h2 id="copy-overloading">
  Перегрузка COPY
</h2>

При [загрузке](#loading) chdb\_hook встраивается в команду Postgres [COPY],
что позволяет копировать данные `TO` или `FROM` в любом из поддерживаемых [форматов данных,
предоставляемых chDB][formats], — в локальные файлы, бакеты [AWS S3], [Google Cloud Storage] и
другие хранилища. Например, чтобы загрузить таблицу из CSV-файла в S3, создайте таблицу,
а затем вызовите `COPY`, указав URL вида `s3://`:

```sql theme={null}
CREATE TABLE times (
    id     INT PRIMARY KEY,
    months INT NOT NULL,
    days   INT NOT NULL
);

COPY times FROM 's3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv';
```

<h3 id="privileges">
  Привилегии
</h3>

Для `COPY` с chdb\_hook требуются те же привилегии, что и для заменяемой им команды [COPY]:
`SELECT` на отношение или на каждый копируемый столбец для `COPY TO` и `INSERT`
для `COPY FROM`. URL вида `file://` читает или записывает файл на сервере, поэтому
также требуется членство в `pg_read_server_files` или `pg_write_server_files`.
Для `COPY FROM` требуется транзакция с возможностью чтения и записи.

<h3 id="url-schemes">
  Схемы URL
</h3>

chdb\_hook выполняется только для тех целей `COPY` в виде URL, которые используют одну из следующих
схем:

| Схемы | Цель | Функция chDB |
| - | - | - |
| `file` | Абсолютный путь на сервере Postgres | [`file()`] |
| `http`, `https` | HTTP URL | [`url()`] |
| `s3` | [AWS S3] | [`s3()`] |
| `gs`, `gcs`, `oss` | [Google Cloud Storage] | [`gcs()`] |
| `az`, `azure`, `abfss`, `abfs` | [Azure Blob Storage] или [Azure ABFS] | [`azureBlobStorage()`] |
| `hdfs` | [Hadoop Distributed File System] | [`hdfs()`] |

<h3 id="url-formats">
  Форматы URL
</h3>

Формат URL зависит от целевой системы (target).

<h4 id="file">
  File
</h4>

<Important>
  Схема `file://` не поддерживается в ClickHouse Cloud.
</Important>

Должен быть абсолютным путём на сервере Postgres. Относительный путь приводит к
ошибке. Пользователь Postgres должен входить в роль `pg_read_server_files` или
`pg_write_server_files` — в зависимости от ситуации. Системный пользователь Postgres должен
иметь доступ к файлу на чтение или запись — в зависимости от ситуации. Для `COPY TO`, если
путь не существует, chdb\_hook создаст все отсутствующие родительские каталоги; для этого
у него должны быть соответствующие разрешения в файловой системе. Пример:

```
file:///tmp/users.parquet
```

<h4 id="http">
  HTTP
</h4>

Любой обычный HTTP URL, в том числе в публичном облачном хранилище. Для `COPY TO`
chdb\_hook попытается отправить данные на этот URL методом `POST`. Пример:

```
https://datasets-documentation.s3.eu-west-3.amazonaws.com/my-test-bucket-768/some_prefix/some_file_1.csv
```

<h4 id="s3">
  S3
</h4>

URL-адреса S3 могут иметь форму S3 URI

```
s3://{bucket}/{path}
```

Либо URL объекта:

```
s3://{bucket}.s3.{region}.amazonaws.com/{path}
```

<h4 id="GCS">
  GCS
</h4>

URL для GCS имеют форму публичного URL:

```
gs://storage.googleapis.com/{bucket}/{path}
```

Либо URI облачного хранилища, который chdb\_hook преобразует в публичный URL:

```
gs://{bucket}/{path}
```

<h4 id="azure-blob-storage">
  Azure Blob Storage
</h4>

Используйте URL вида `blob.windows.net`, указав имя аккаунта в качестве субдомена:

```
az://{account}.blob.core.windows.net/{container}/{blob}
```

Либо используйте другое имя хоста:

```
az://{host}/{container}/{blob}
```

<h4 id="azure-abfs">
  Azure ABFS
</h4>

URL-адреса ABFS должны иметь следующий формат:

```
abfs://{container}@{account}.dfs.core.windows.net/{blob}
```

<h4 id="hdfs-urls">
  URL-адреса HDFS
</h4>

URL-адреса HDFS могут задаваться в обычном HTTP-подобном формате с необязательным указанием порта:

```
hdfs://{host}/{path}
hdfs://{host}:{port}/{path}
```

<h3 id="path-wildcards">
  Подстановочные шаблоны в путях
</h3>

URL-пути в командах `COPY FROM` могут содержать глоб-шаблоны. Файлы должны соответствовать
шаблону пути целиком, а не только его суффиксу или префиксу. Единственное исключение: если
путь указывает на существующий каталог и не содержит глоб-шаблонов, к пути неявно
добавляется `*`, чтобы выбрать все файлы в этом каталоге.

Поддерживаемые подстановочные шаблоны:

* `*`: соответствует произвольному количеству символов, кроме `/`, включая пустую строку.
* `?`: соответствует любому одиночному символу.
* `{groucho,harpo,chico}`: подставляет любую из строк «groucho», «harpo» и
  «chico». Строки могут содержать `/`.
* `{N..M}`: соответствует любому числу `>= N` и `<= M`.
* `**`: рекурсивно соответствует всем файлам в каталоге.

Например, чтобы загрузить данные из этих файлов одной командой:

* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;1.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;1.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;2.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;2.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;3.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/some\&#95;prefix/some\&#95;file\&#95;3.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;1.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;1.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;2.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;2.csv)
* [https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;3.csv](https://clickhouse-public-datasets.s3.amazonaws.com/my-test-bucket-768/another\&#95;prefix/some\&#95;file\&#95;3.csv)

Используйте `{some,another}_prefix`, чтобы охватить оба имени каталогов, и
`some_file_{1..3}.csv'`, чтобы охватить нужные файлы — вот так:

```sql theme={null}
CREATE TABLE times (
    id     INT NOT NULL,
    months INT NOT NULL,
    days   INT NOT NULL
);

COPY times FROM 's3://datasets-documentation/my-test-bucket-768/{some,another}_prefix/some_file_{1..3}.csv';
```

<h3 id="options">
  Параметры
</h3>

Команда `COPY` в chdb\_hook поддерживает следующие параметры:

<h4 id="format">
  `format`:
</h4>

Формат для чтения или записи. Должен быть одним из [formats], поддерживаемых [chDB],
среди которых TSV, CSV, Parquet, Iceberg, JSON и другие. Опустите этот параметр или задайте значение
`auto`, чтобы chDB определил формат по расширению имени файла в конце
URL.

<h4 id="structure">
  `structure`
</h4>

Структура данных [chDB] для строки. Состоит из списка имён столбцов, \[типов данных ClickHouse] и модификаторов. Если параметр не указан, chdb\_hook сопоставляет типы данных Postgres с наиболее подходящими типами ClickHouse; подробнее см. [Postgres в chDB](#postgres-to-chdb). Если задано значение `auto`, chDB пытается определить типы автоматически.

Пример:

```sql theme={null}
COPY users TO 'file:///tmp/users.parquet' (
    structure 'id Int64, name String, age Nullable(UInt8), attributes JSON'
);
```

<h4 id="access_key-and-access_secret">
  `access_key` и `access_secret`
</h4>

Долгосрочные учётные данные пользователя AWS account для аутентификации запросов.

* **S3:** AWS \[ключ доступа ID и access secret], которые чаще всего задаются переменными окружения `AWS_ACCESS_KEY_ID` и `AWS_SECRET_ACCESS_KEY`
* **GCS:** GCP [HMAC key and secret]
* **Azure:** имя Azure Storage account и \[ключ доступа]

<h4 id="session_token">
  `session_token`
</h4>

Сеансовый токен AWS, используемый вместе с `access_key` и `access_secret`; часто
задаётся переменной окружения `AWS_SESSION_TOKEN`. Применяется только для
URL-адресов S3.

<h4 id="compression">
  `compression`
</h4>

Формат сжатия файла. Используйте, если сжатие нельзя определить по имени
файла. Поддерживаемые значения:

* `auto` (по умолчанию)
* `none`
* `gzip` или `gz`
* `brotli` или `br`
* `xz` или `LZMA`
* `zstd` или `zst`
* `lz4`
* `bz2`
* `snappy`

<h4 id="timeout">
  `timeout`
</h4>

Тайм-аут запроса в миллисекундах. Применяется к URL-адресам HTTP, S3, GCS и Azure.
Значение по умолчанию — `30000` (30 с).

<h4 id="encoding_check">
  `encoding_check`
</h4>

Определяет, как обрабатывать недопустимые символы в [database encoding] при
преобразовании значений chDB типов String и JSON. Возможные значения:

* `fail` (по умолчанию): сгенерировать ошибку
* `remove`: удаляет недопустимые байты
* `replace`: в кодировании UTF-8 заменяет недопустимые байты
  символом замены Unicode (`�`); для других кодирований
  работает так же, как `remove`
* `truncate`: обрезает текст по первому недопустимому байту

<h3 id="debugging">
  Отладка
</h3>

При ошибке команда `COPY` из chdb\_hook добавляет в контекст ошибки
запрос chDB, который она пыталась выполнить:

```
ERROR:  chdb: error executing chDB query
DETAIL:  Code: 53. DB::Exception: Requested type of column p doesn't match parquet schema
CONTEXT:  query: SELECT * FROM file({path:String}, {format:String}, {structure:String})
STATEMENT:  COPY "users" FROM 'file:///tmp/users.data' (format 'Parquet');
```

chdb\_hook использует плейсхолдеры вида `{name:Type}` для параметров запроса,
чтобы защититься от SQL-инъекций и снизить риск
попадания в журнал конфиденциальных данных, например учётных данных.

Если же вам нужно посмотреть содержимое этих параметров для отладки
проблемы, временно задайте для GUC Postgres \[log\_min\_messages] значение `DEBUG1` или
выше — тогда chdb\_hook будет отправлять запрос и параметры в журнал Postgres
(но никогда не клиенту), где они будут выглядеть так:

```
2026-08-08 09:41:06.842 EDT [59940] LOG:  executing chDB query
2026-08-08 09:41:06.842 EDT [59940] DETAIL:  query: SELECT * FROM file({path:String}, {format:String}, {structure:String})
2026-08-08 09:41:06.842 EDT [59940] CONTEXT:  params: { path: "/tmp/users.data", format: "Parquet", structure: "user_id Nullable(Int64), username Nullable(String), password Nullable(String)" }
2026-08-08 09:41:06.842 EDT [59940] STATEMENT:  COPY "users" FROM 'file:///tmp/users.data' (format 'Parquet');
```

<Warning>
  Не оставляйте \[log\_min\_messages] на уровне отладки дольше, чем на один
  сеанс отладки: это позволит избежать попадания в журнал конфиденциальных данных,
  таких как учётные данные, к тому же PostgreSQL и сам пишет отладочную информацию
  и может быстро заполнить журнал.
</Warning>

<h2 id="create-table-overloading">
  Перегрузка CREATE TABLE
</h2>

chdb\_hook также встраивается в [CREATE TABLE], благодаря чему таблица может
получать свои столбцы и загружать строки из URL.

Чтобы создать таблицу со структурой, полученной из URL, передайте URL в
параметре `structure_from` и оставьте список столбцов пустым (имейте в виду: этот общедоступный
файл данных содержит 41 млн строк):

```sql theme={null}
CREATE TABLE reviews () WITH (
    encoding_check = 'replace',
    structure_from = 's3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet'
);
```

Используйте `copy_from`, чтобы загрузить не только столбцы, но и строки:

```sql theme={null}
CREATE TABLE reviews () WITH (
    encoding_check = 'replace',
    copy_from = 's3://datasets-documentation/amazon_reviews/amazon_reviews_2015.snappy.parquet'
);
```

`copy_from` определяет столбцы автоматически только в том случае, если сам оператор не задаёт ни одного столбца. Список столбцов, clause `INHERITS`, тип в `OF` или партиция — каждый из них задаёт столбцы, поэтому в таком случае `copy_from` копирует только:

```sql theme={null}
CREATE TABLE times (
    id     INT NOT NULL,
    months INT NOT NULL,
    days   INT NOT NULL
) WITH (copy_from = 's3://datasets-documentation/my-test-bucket-768/some_prefix/some_file_1.csv');
```

Когда `copy_from` определяет столбцы автоматически, он использует схему источника, возвращаемую `DESCRIBE`.
Поэтому значения `Map`, `Tuple` и `Nested` загружаются как текстовые столбцы типа Array,
по которым нельзя определить их исходные типы ClickHouse.

Оба варианта поддерживают те же [схемы URL](#url-schemes) и
[options](#options), что и `COPY`: учётные данные, format, сжатие, тайм-аут и
даже явно заданная [structure](#structure) — всё это работает. Postgres сохраняет все
оставшиеся storage parameters:

```sql theme={null}
CREATE TABLE logs () WITH (
    copy_from  = 's3://chdb-lakedata-public/logs/logs-2026-08-26.csv',
    format     = 'CSVWithNames',
    timeout    = 60000,
    fillfactor = 90
);
```

Ни `structure_from`, ни `copy_from` не работают с `IF NOT EXISTS`. Для загрузки
существующего отношения используйте [COPY].

<h2 id="limitations">
  Ограничения
</h2>

Из-за ряда известных проблем и различий в поведении типов данных
между Postgres и chDB у chdb\_hook есть следующие ограничения:

* Невозможно выполнить `COPY` для отношений с политиками \[безопасность на уровне строк],
  которые применяются к копирующей роли. Postgres применяет такие политики,
  переписывая `COPY TO` в запрос, а chdb\_hook этого не поддерживает.
* Невозможно выполнить `COPY FROM` из URL с предложением `WHERE`.
* В chDB нет NULL-массива, поэтому вместо NULL `COPY TO` сохраняет пустой массив (`[]`).
* chDB представляет эквиваленты `lseg`, `path` и `polygon` в виде массивов,
  поэтому NULL-значения этих типов при `COPY TO` также превращаются в пустой массив (`[]`).
* В ClickHouse нет NULL-массива, поэтому вместо `NULL` `COPY TO` сохраняет пустой массив (`[]`).
* ClickHouse представляет эквиваленты `lseg`, `path` и `polygon` в виде
  массивов, поэтому NULL-значения этих типов при `COPY TO` также превращаются в пустой массив
  (`[]`).
* Если в заданной [структуре](#structure) столбец не определён как Nullable,
  NULL-значения будут выведены как значения по умолчанию. Всегда
  явно определяйте столбцы с типом Nullable в [структуре](#structure), чтобы избежать
  такого преобразования.
* Незамкнутый `path`, последняя точка которого совпадает с первой, выводится как замкнутый путь.
* В Protobuf в повторяющемся поле нет null, поэтому NULL-значения в массивах опускаются.
* [JSON type] в chDB поддерживает только объекты JSON; заменяйте отображение по умолчанию
  `String` для `json` и `jsonb` на `JSON` только в том случае, если все значения являются
  объектами JSON. (ClickHouse/ClickHouse#68428)
* [JSON type] в chDB игнорирует `null`: ключи объекта со значениями NULL будут
  опущены при выводе. Заменяйте отображение по умолчанию `String` для `json` и
  `jsonb` на `JSON` только в том случае, если значения объекта не равны `null` либо их потеря
  допустима. (ClickHouse/ClickHouse#68428)
* Форматы JSON, JSONCompact и JSONColumnsWithMetadata всегда проверяют
  UTF-8, поэтому выводят значения bytea с символами замены.
* `COPY FROM` читает поле Protobuf `Nullable`, содержащее пустую строку или
  ноль, как `NULL`. (chdb-io/chdb-core#152)
* `COPY TO` в Parquet отбрасывает `NULL` из собственного null map типа Nullable Tuple.
  (ClickHouse/ClickHouse#112427)
* В форматах Parquet, Arrow, ArrowStream, ORC, Avro, Protobuf, ProtobufList, MsgPack
  и BSONEachRow нет типа, соответствующего `time` в Postgres или
  `Time64` в chDB. Чтобы сохранить значения, задавайте столбцы `time` как `String` в явной
  [структуре](#structure).
* Вывод Protobuf усекает значения временных меток до секунд.
* Вывод Protobuf не поддерживает даты ранее 1970-01-01. Чтобы сохранить значения,
  задавайте столбцы `time` как `String` в явной [структуре](#structure). (ClickHouse/ClickHouse#111860)

<h2 id="data-types">
  Типы данных
</h2>

[COPY](#copy-overloading) сопоставляет типы Postgres отношения с типами chDB,
а [CREATE TABLE](#create-table-overloading) — типы chDB для URL
с типами Postgres.

<h3 id="postgres-to-chdb">
  Из Postgres в chDB
</h3>

Если параметр [structure](#structure) не задан явно, chdb\_hook сопоставляет
типы Postgres с подходящими эквивалентами в chDB. Если они не подходят для
вашего сценария, укажите [structure](#structure), чтобы заменить
сгенерированные типы нужными.

| PostgreSQL | chDB | Примечания |
| - | - | - |
| boolean | Bool | |
| smallint | Int16 | |
| integer | Int32 | |
| bigint | Int64 | |
| oid | UInt32 | |
| xid8 | UInt64 | |
| oid8 | UInt64 | |
| real | Float32 | |
| double precision | Float64 | |
| numeric | Decimal256(38) | Также если точность превышает 76 цифр. |
| numeric(12,6) | Decimal(12,6) | Точность и масштаб сохраняются. |
| text | String | |
| bytea | String | |
| date | Date32 | |
| time | Time64(6) | Для форматов, не поддерживающих время, замените на `String`. |
| timestamp | DateTime64(6, 'UTC') | Преобразуется из часового пояса сеанса. |
| timestamptz | DateTime64(6, 'UTC') | |
| interval | String | Замените на единицу `Interval`, например `IntervalDay`. |
| uuid | UUID | |
| json | String | Замените на `JSON`, если данные содержат только объекты. |
| jsonb | String | Замените на `JSON`, если данные содержат только объекты. |
| inet | String | Замените на `IPv4` или `IPv6`, если данные содержат адреса только одного вида. |
| point | Point | Те же две координаты, что и в Postgres. |
| lseg | LineString | Линия ровно из двух точек. |
| path | LineString | В замкнутом пути первая точка повторяется в конце. |
| polygon | Ring | Кольцо замыкается неявно, как и многоугольник. |
| box | Tuple(high Point, low Point) | Два угла, упорядоченные так же, как в Postgres. |
| circle | Tuple(center Point, radius Float64) | |
| line | Tuple(a Float64, b Float64, c Float64) | Уравнение `Ax + By + C = 0`. |

Типы, отсутствующие в этой таблице, например `name`, `varchar`, `char`, `bit`,
`timetz`, `money` и перечисления, сопоставляются с `String`.

Типы массивов сопоставляются с `Array` из сопоставленного типа элементов. В ClickHouse
допустимость NULL задаётся на уровне столбца, а в Postgres — на уровне массива, поэтому элементы
всегда имеют тип `Nullable`.

Ни один тип Postgres не сопоставляется напрямую с `Map`, `Tuple` или `Nested`, однако
их можно указать в [structure](#structure) или в исходном файле. `Tuple` можно прочитать
в `text[]` (по одному элементу на каждое поле кортежа) или в соответствующий [составной
тип][composite
type], чтобы сохранить типы полей. `Map` или `Nested` можно прочитать в
`text[][]` (по одному вложенному массиву на каждую пару ключ-значение или вложенный кортеж) или в
массив соответствующего составного типа. Примеры см. в разделе [Ручное сопоставление
типов](#manual-type-mappings).

<h3 id="timestamp-conversion">
  Преобразование временных меток
</h3>

В текстовых форматах (TSV, CSV и др.) hook `COPY` выводит значения DateTime и
DateTime64 в формате ISO-8601, `YYYY-MM-DDThh:mm:ssZ`, независимо от текущего
значения настройки `datestyle`. Это гарантирует, что значения timestamptz
останутся согласованными, даже если система, импортирующая эти значения,
использует другой часовой пояс. Указание другого типа в выводе `structure`,
например `Datetime64(3, 'America/Los_Angeles')`, не влияет на смещение в
выводе, но меняет precision.

Примеры Timestamp TZ:

| timestamptz | `DateTime64(6, 'UTC')` | `DateTime64(3 'Japan')` |
| - | - | - |
| `2026-08-28T12:00:00Z` | `2026-08-28T12:00:00.000000Z` | `2026-08-28T12:00:00.000Z` |
| `2026-08-28T11:00:00 America/Los_Angeles` | `2026-08-28T18:00:00.000000Z` | `2026-08-28T18:00:00.000Z` |
| `2026-08-28T10:00:00.723923 Asia/Tokyo` | `2026-08-28T01:00:00.723923Z` | `2026-08-28T01:00:00.723Z` |

Hook `COPY` также переводит значения timestamp из часового пояса сеанса в
UTC, благодаря чему они выводятся относительно этого часового пояса. При
загрузке в новую систему та должна преобразовать их в свой локальный часовой
пояс. Таким образом, сами значения будут различаться при разных часовых
поясах, но будут совпадать с точностью до разницы часовых поясов.

Пример влияния настройки `timezone` на временную метку
`2026-08-28T12:00:00`:

| настройка timezone | `DateTime64(6, 'UTC')` | `DateTime64(3 'Japan')` |
| - | - | - |
| `UTC` | `2026-08-28T12:00:00.000000Z` | `2026-08-28T12:00:00.000Z` |
| `America/Los_Angeles` | `2026-08-28T19:00:00.000000Z` | `2026-08-28T19:00:00.000Z` |
| `America/New_York` | `2026-08-28T16:00:00.000000Z` | `2026-08-28T16:00:00.000Z` |
| `Japan` | `2026-08-28T03:00:00.000000Z` | `2026-08-28T03:00:00.000Z` |

<h3 id="chdb-to-postgres">
  Из chDB в Postgres
</h3>

Для существующих таблиц значения преобразуются к объявленным типам столбцов.
Для альтернативных скалярных типов используются явные приведения PostgreSQL (если они есть), а
элементы массивов преобразуются к объявленному типу элементов. Неподдерживаемые
преобразования и значения, выходящие за допустимый диапазон, вызывают ошибки.

Сопоставляйте типы chDB `Interval` с `smallint`, `integer` или `bigint`, чтобы читать и
записывать количество соответствующих единиц. Например, значение `IntervalDay`, равное `3`, сопоставляется
с целым числом `3`. При сопоставлении `IntervalNanosecond` с `bigint` наносекунды
сохраняются, а при сопоставлении с `interval` значение усекается до микросекунд.

При создании таблиц на основе типов ClickHouse, возвращаемых [`DESCRIBE`], chdb\_hook использует
приведённые ниже типы Postgres по умолчанию. Дополнительные целевые типы для чтения применяются к
явно объявленным столбцам и включают преобразования, выходящие за рамки явных приведений
PostgreSQL. Пустые ячейки не означают, что эти приведения недоступны. Указанные целевые типы относятся только к чтению;
для записи действуют отдельные правила преобразования.

| chDB | PostgreSQL по умолчанию | Дополнительные целевые типы при чтении | Примечания |
| - | - | - | - |
| Array(T) | T\[] | | Отдельный тип массива PG для каждого уровня вложенности |
| BFloat16 | real | | |
| Bool | boolean | | |
| Date | date | | |
| Date32 | date | | |
| DateTime | timestamp with time zone | time | |
| DateTime64(P) | timestamp(P) with time zone | time | Значения P больше 6 ограничиваются до 6 |
| Decimal(P,S) | numeric(P,S) | xid8, oid8 | |
| Decimal32(S) | numeric(9,S) | xid8, oid8 | |
| Decimal64(S) | numeric(18,S) | xid8, oid8 | |
| Decimal128(S) | numeric(38,S) | xid8, oid8 | |
| Decimal256(S) | numeric(76,S) | xid8, oid8 | |
| Enum8 | text | bytea; типы, совместимые по входному формату | Декодируется в метку; подходят перечисления PG с совпадающими метками |
| Enum16 | text | bytea; типы, совместимые по входному формату | Декодируется в метку; подходят перечисления PG с совпадающими метками |
| FixedString(N) | text | bytea; типы, совместимые по входному формату | Завершающие NUL-символы сохраняются только в bytea |
| Float32 | real | | |
| Float64 | double precision | | |
| IPv4 | inet | | |
| IPv6 | inet | | |
| Int8 | smallint | boolean | Ноль — false, ненулевое значение — true |
| Int16 | smallint | boolean | Ноль — false, ненулевое значение — true |
| Int32 | integer | | |
| Int64 | bigint | | |
| Int128 | numeric(39,0) | xid8, oid8 | |
| Int256 | numeric(77,0) | xid8, oid8 | |
| IntervalDay | interval | smallint, integer, bigint | В целочисленные типы записывается количество единиц |
| IntervalHour | interval | smallint, integer, bigint | В целочисленные типы записывается количество единиц |
| IntervalMicrosecond | interval | smallint, integer, bigint | В целочисленные типы записывается количество единиц |
| IntervalMillisecond | interval | smallint, integer, bigint | В целочисленные типы записывается количество единиц |
| IntervalMinute | interval | smallint, integer, bigint | В целочисленные типы записывается количество единиц |
| IntervalMonth | interval | smallint, integer, bigint | Целые числа содержат количество единиц |
| IntervalNanosecond | interval | smallint, integer, bigint | Целые числа сохраняют наносекунды; interval усекает значение до микросекунд |
| IntervalQuarter | interval | smallint, integer, bigint | Целые числа содержат количество единиц |
| IntervalSecond | interval | smallint, integer, bigint | Целые числа содержат количество единиц |
| IntervalWeek | interval | smallint, integer, bigint | Целые числа содержат количество единиц |
| IntervalYear | interval | smallint, integer, bigint | Целые числа содержат количество единиц |
| JSON | jsonb | json, text, bytea; типы, совместимые по вводу | jsonb нормализует документ |
| LineString | path | lseg | Для lseg требуются ровно две точки |
| LowCardinality(T) | T | | |
| Map(K,V) | text\[]\[] | composite\[], T\[]\[], text | Одна строка текстовых элементов на каждую пару |
| MultiLineString | path\[] | | |
| MultiPolygon | polygon\[]\[] | | |
| Nested(...) | text\[]\[] | composite\[], T\[]\[], text | Одна строка текстовых элементов на каждую вложенную строку |
| Nullable(T) | T | | Делает столбец допускающим NULL |
| Point | point | | |
| Polygon | polygon\[] | | |
| Ring | polygon | lseg | Для lseg требуются ровно две точки |
| SimpleAggregateFunction(f,T) | T | | Хранит значения как T |
| String | text | bytea; типы, совместимые по вводу | bytea сохраняет необработанные байты |
| Time | time without time zone | | |
| Time64(P) | time(P) without time zone | | Значения P больше 6 ограничиваются до 6 |
| Tuple(...) | text\[] | composite, T\[], text; box, circle, line | Поля преобразуются в текстовые элементы |
| UInt8 | smallint | boolean | Ноль — false; ненулевое значение — true |
| UInt16 | integer | | |
| UInt32 | bigint | | |
| UInt64 | numeric(20,0) | xid8, oid8 | |
| UInt128 | numeric(39,0) | xid8, oid8 | |
| UInt256 | numeric(78,0) | xid8, oid8 | |
| UUID | uuid | | |

Типы, совместимые по вводу, можно читать из строковых значений с помощью их функции ввода PostgreSQL.
Составные типы должны иметь совпадающие поля в совпадающем порядке. Чтобы прочитать кортеж
как массив, каждое поле должно преобразовываться в тип элемента массива, и ни одно поле
само не может быть массивом.

При чтении в виде массива `Map` использует одну строку на каждую пару ключ-значение, а `Nested` —
одну строку на каждую вложенную строку. Чтобы прочитать кортеж как `box`, укажите две точки; для
`circle` укажите точку и радиус; для `line` укажите три коэффициента.

Любой тип chDB, отсутствующий в этой таблице, приводит к ошибке — в том числе `Variant`,
`Dynamic` и `AggregateFunction`. Чтобы читать их как текст, используйте [structure](#structure), сопоставляющую
их с `String`.

Для некоторых из этих типов Postgres поддерживает более узкий диапазон, чем chDB, поэтому копирование
завершается ошибкой для `Time` или `Time64` свыше 24 часов, а также для `Date32`
за пределами диапазона дат Postgres.

<h3 id="manual-type-mappings">
  Ручное сопоставление типов
</h3>

При автоматическом определении столбцов для перечислений используется `text`, а для значений `Tuple`, `Map`
и `Nested` — текстовые массивы. Чтобы сохранить типы полей или ограничить допустимые значения перечислений, создайте
в PostgreSQL перечисляемые и составные типы, а затем объявите столбцы с этими типами.
Задайте типы chDB с помощью [structure](#structure) или используйте `structure 'auto'`,
чтобы они определялись по исходным данным, а не по таблице Postgres. Например,
с помощью следующих типов можно загрузить статусы событий, координаты, метки и
вложенные элементы:

```sql theme={null}
CREATE TYPE event_status AS ENUM ('new', 'done');
CREATE TYPE event_point AS (x integer, y integer);
CREATE TYPE event_label AS (key text, value bigint);
CREATE TYPE event_item AS (id integer, name text);

CREATE TABLE events (
    status event_status,
    point  event_point,
    labels event_label[],
    items  event_item[]
);

COPY events FROM 's3://chdb-lakedata-public/examples/events.parquet' (
    structure $$
        status Enum8('new' = 1, 'done' = 2),
        point  Tuple(Int32, Int32),
        labels Map(String, Int64),
        items  Array(Tuple(id Int32, name String))
    $$
);
```

Объявляйте поля составных типов в том же порядке, что и поля в chDB, используя совместимые типы PostgreSQL.
Для значений `Map` объявите сначала поле ключа, а затем поле значения. Каждый
`Tuple` преобразуется в одно составное значение; каждая пара `Map` или строка `Nested` — в
один элемент массива составного типа.

Если `structure` задан явно, chDB разбивает `Nested` на отдельные столбцы типа `Array` — по одному на каждое
поле. Чтобы считать вложенные строки в один столбец с массивом составного типа, используйте `Array(Tuple(...))`,
как показано выше, либо укажите `structure 'auto'`, если исходный формат chDB
содержит информацию о типах.

<h3 id="text-encoding">
  Кодирование текста
</h3>

chDB читает `String`, `FixedString`, `Enum` и `JSON` как байты, без каких-либо
гарантий кодирования. При копировании такого столбца в `text` или в любой другой
небинарный тип байты проверяются на соответствие кодированию базы данных, и для
данных, которые невозможно представить, вызывается ошибка:

```
ERROR:  invalid byte sequence for encoding "UTF8": 0x00
```

Любое кодирование отвергает NUL-символы, которые Postgres не может хранить в `text`.

Копируйте в `bytea`, чтобы сохранить байты в том виде, в котором их записал chDB. Задавайте таким полям соответствующие имена, поскольку [CREATE TABLE](#create-table-overloading) выводит для этих типов `text`:

```sql theme={null}
CREATE TABLE logs (req_id numeric(20,0), resource bytea) WITH (
    copy_from = 's3://chdb-lakedata-public/logs/logs-2026-08-26.parquet'
);
```

`FixedString(N)` дополняет более короткие значения байтами NUL. При копировании в `text` завершающие NUL отбрасываются, тогда как `bytea` сохраняет все N байт.

<h2 id="settings">
  Настройки
</h2>

<h3 id="chdb_hookmax_memory">
  `chdb_hook.max_memory`
</h3>

```sql theme={null}
SET chdb_hook.max_memory = '1 GB';
```

Определяет максимальный объём памяти для запроса chDB; используется для установки настройки chDB
[`max_memory_usage`]. Требует привилегий суперпользователя. Укажите целое число, задающее
количество мегабайт, либо значение с одной из следующих единиц измерения памяти:

* `B` (байты)
* `kB` (килобайты)
* `MB` (мегабайты)
* `GB` (гигабайты)
* `TB` (терабайты)

Значение по умолчанию — `0`: память не ограничивается.

<h3 id="chdb_hookmax_threads">
  `chdb_hook.max_threads`
</h3>

```sql theme={null}
SET chdb_hook.max_threads = 4;
```

Максимальное количество потоков обработки запросов для запроса chDB; используется для установки настройки chDB [`max_threads`]. Требует привилегий суперпользователя. Значение по умолчанию — `0`: в этом случае chDB определяет значение самостоятельно.

Мы настоятельно рекомендуем задавать `chdb_hook.max_threads` перед выполнением крупной операции `COPY`, чтобы chDB не загружал CPU полностью в ущерб PostgreSQL.

<h3 id="chdb_hookmax_parsing_threads">
  `chdb_hook.max_parsing_threads`
</h3>

```sql theme={null}
SET chdb_hook.max_parsing_threads = 2;
```

Максимальное число потоков, которые chDB может использовать для разбора данных во входных форматах, поддерживающих параллельный разбор; используется для установки настройки chDB [`max_parsing_threads`]. Требует привилегий суперпользователя. Значение по умолчанию — `0`: в этом случае chDB определяет значение самостоятельно.

Рекомендуем задавать `chdb_hook.max_parsing_threads` перед выполнением `COPY` для больших объёмов данных, чтобы chDB не загружал CPU до предела в ущерб PostgreSQL.

<h2 id="versioning-policy">
  Политика версионирования
</h2>

chdb\_hook придерживается [Semantic Versioning] для своих публичных релизов.

* Мажорная версия увеличивается при изменениях API
* Минорная версия увеличивается при обратно совместимых изменениях SQL
* Патч-версия увеличивается при изменениях, затрагивающих только бинарный файл

После установки версию можно узнать с помощью функции
[`pg_get_loaded_modules()`] в Postgres 18.

```sql theme={null}
SELECT version FROM pg_get_loaded_modules() WHERE module_name = 'chdb_hook';
```

<h2 id="authors">
  Авторы
</h2>

* [David E. Wheeler](https://justatheory.com/)
* [serprex](https://github.com/serprex)

<h2 id="copyright">
  Авторские права
</h2>

Copyright (c) 2026, ClickHouse

[chDB]: https://clickhouse.com/chdb "chDB — быстрая, надёжная и масштабируемая встраиваемая база данных"

[Semantic Versioning]: https://semver.org/spec/v2.0.0.html "Semantic Versioning 2.0.0"

[COPY]: https://www.postgresql.org/docs/current/sql-copy.html "Документация Postgres: COPY"

[CREATE TABLE]: https://www.postgresql.org/docs/current/sql-createtable.html "Документация Postgres: CREATE TABLE"

[`DESCRIBE`]: https://clickhouse.com/docs/sql-reference/statements/describe-table "ClickHouse Docs: DESCRIBE TABLE"

[formats]: https://github.com/chdb-io/chdb/blob/main/refs/clickhouse-formats-settings.md#complete-format-names-table "Документация chDB: полная таблица имён форматов"

[access key ID and access secret]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html "AWS Identity and Access Management: управление ключами доступа для пользователей IAM"

[HMAC key and secret]: https://docs.cloud.google.com/storage/docs/authentication/hmackeys "Google Cloud Storage: HMAC-ключи"

[access key]: https://learn.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?tabs=azure-cli "Azure: управление ключами доступа к учётной записи хранения"

[row-level security]: https://www.postgresql.org/docs/current/ddl-rowsecurity.html "Документация Postgres: политики безопасности на уровне строк"

[JSON type]: /reference/data-types/newjson "ClickHouse Docs: тип данных JSON"

[LOAD]: https://www.postgresql.org/docs/current/sql-load.html "Документация Postgres: LOAD"

[session_preload_libraries]: https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SESSION-PRELOAD-LIBRARIES "Документация Postgres: `session_preload_libraries`"

[shared_preload_libraries]: https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SESSION-PRELOAD-LIBRARIES "Документация Postgres: `shared_preload_libraries`"

[ALTER SYSTEM]: https://www.postgresql.org/docs/18/sql-altersystem.html "Документация Postgres: ALTER SYSTEM"

[ALTER DATABASE]: https://www.postgresql.org/docs/current/sql-alterdatabase.html "Документация Postgres: ALTER DATABASE"

[ALTER ROLE]: https://www.postgresql.org/docs/18/sql-alterrole.html "Документация Postgres: ALTER ROLE"

[AWS S3]: https://aws.amazon.com/s3/ "Объектное хранилище Cloud — Amazon S3 — Amazon Web Services"

[Google Cloud Storage]: https://cloud.google.com/storage "Cloud Storage — Google Cloud"

[`file()`]: https://clickhouse.com/docs/sql-reference/table-functions/file "ClickHouse Docs: табличная функция file"

[`url()`]: https://clickhouse.com/docs/sql-reference/table-functions/url "ClickHouse Docs: табличная функция url"

[`s3()`]: https://clickhouse.com/docs/sql-reference/table-functions/s3 "ClickHouse Docs: табличная функция s3"

[`gcs()`]: https://clickhouse.com/docs/sql-reference/table-functions/gcs "ClickHouse Docs: табличная функция gcs"

[Azure Blob Storage]: https://azure.microsoft.com/en-us/products/storage/blobs/

[Azure ABFS]: https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction-abfs-uri "Использование URI Azure Data Lake Storage (ABFS) — Azure Storage"

[`azureBlobStorage()`]: https://clickhouse.com/docs/sql-reference/table-functions/azureBlobStorage "ClickHouse Docs: табличная функция azureBlobStorage"

[Hadoop Distributed File System]: https://en.wikipedia.org/wiki/Apache_Hadoop#Overview "Википедия: обзор Apache Hadoop"

[`hdfs()`]: https://clickhouse.com/docs/sql-reference/table-functions/hdfs "ClickHouse Docs: табличная функция hdfs"

[ClickHouse data types]: https://clickhouse.com/docs/reference/data-types/index "ClickHouse Docs: типы данных в ClickHouse"

[composite type]: https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-DECLARING "Документация PostgreSQL: объявление составных типов"

[log_min_messages]: https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-MIN-MESSAGES "Документация PostgreSQL: log_min_messages"

[`pg_get_loaded_modules()`]: https://pgpedia.info/g/pg_get_loaded_modules.html "pgPedia: pg_get_loaded_modules()"

[`max_memory_usage`]: https://clickhouse.com/docs/reference/settings/session-settings/max-memory-usage "ClickHouse Docs: настройки сеанса max_memory_usage_*"

[`max_threads`]: https://clickhouse.com/docs/reference/settings/session-settings/max-threads "ClickHouse Docs: настройки сеанса max_threads_*"

[`max_parsing_threads`]: https://clickhouse.com/docs/reference/settings/session-settings/max#max_parsing_threads "ClickHouse Docs: настройка сеанса max_parsing_threads"

[database encoding]: https://www.postgresql.org/docs/current/multibyte.html "PostgreSQL Docs: поддержка кодировок"
