/datamarts[/{datamart}]/query

Содержание раздела
  1. Режимы выполнения запросов
  2. Формат ответа
    1. Поддерживаемые форматы данных
    2. Avro-формат ответа
    3. Состав ответов при потоковом чтении данных
  3. Режимы чтения данных
  4. URL
  5. Заголовки запроса
    1. Ограничения x-request-id
  6. Тело запроса
  7. Примеры запросов
    1. Чтение данных одной порцией
    2. Потоковое чтение порциями заданного размера
      1. Потоковое чтение данных в Avro-формате
      2. Потоковое чтение данных в JSON-формате
    3. Обновление данных в синхронном режиме
    4. Обновление данных в асинхронном режиме
    5. Подготовленный запрос (prepared statement)

POST-метод выполняет запрос SQL+, заданный в теле сообщения. Поддерживается как выполнение простого вопроса, так и подготовленного запроса (prepared statement).

Запрос можно выполнить в выбранной логической базе данных. Чтобы выбрать логическую БД, укажите ее имя в URL.

Режимы выполнения запросов

Запросы на загрузку, обновление и выгрузку данных можно выполнить в синхронном или асинхронном режиме. Остальные запросы выполняются в синхронном режиме.

Режим выполнения задается параметром async в теле запроса. По умолчанию, если параметр async имеет значение false или не задан, запрос исполняется в синхронном режиме и система возвращает ответ только после завершения обработки запроса; если параметр имеет значение true, ответ возвращается при принятии запроса на обработку, а не по завершении обработки.

Формат ответа

Поддерживаемые форматы данных

Метод поддерживает возврат данных в различных форматах — JSON, Avro и plain. По умолчанию метод возвращает ответ в JSON-формате. При необходимости вы можете задать другой формат ответа с помощью параметра format в URL.

Avro-формат ответа

При использовании Avro-формата ответа в поле doc схемы Avro возвращается информация о логических типах данных, содержащихся в выборке, как показано в примере ниже.

Для столбца с неопределенным типом в поле doc указывается тип ANY, а в поле fields указывается union-элемент со всеми типами Avro (см. пример ниже для столбца test_column). Пример запроса, в котором столбец test_column имеет неопределенный тип данных: SELECT *, null AS test_column FROM marketing.sales.

Пример схемы Avro в ответе, представленной для наглядности в JSON-формате:

{
  "type": "record",
  "name": "resultSet",
  "namespace": "prostore",
  "doc": {
    "metadata": [
      {
        "name": "id",
        "type": "BIGINT",
        "size": null,
        "nullable": false
      },
      {
        "name": "transaction_date",
        "type": "TIMESTAMP",
        "size": 6,
        "nullable": false
      },
      {
        "name": "product_code",
        "type": "VARCHAR",
        "size": 256,
        "nullable": false
      },
      {
        "name": "product_units",
        "type": "BIGINT",
        "size": null,
        "nullable": false
      },
      {
        "name": "store_id",
        "type": "BIGINT",
        "size": null,
        "nullable": false
      },
      {
        "name": "description",
        "type": "VARCHAR",
        "size": 256,
        "nullable": true
      },
      {
        "name": "test_column",
        "type": "ANY",
        "size": null,
        "nullable": true
      }  
    ]
  },
  "fields": [
    {"name": "id", "type": "long"},
    {"name": "transaction_date", "type": {"type": "long", "logicalType": "timestamp-micros"}},
    {"name": "product_code", "type": {"type": "string", "avro.java.string": "String"}},
    {"name": "product_units", "type": "long"},
    {"name": "store_id", "type": "long"},
    {"name": "description", "type": ["null", {"type": "string", "avro.java.string": "String"}], "default": null},
    {"name" : "test_column", "type" : [ "null", "long", "double", "int", "float", "boolean", {"type" : "string", "avro.java.string" : "String"}], "default" : null}
  ]
}

Состав ответов при потоковом чтении данных

При потоковом чтении данных ответы возвращаются в следующем виде:

  • в JSON-формате:
    • первый ответ потока содержит массив metadata с логической схемой данных, а также пустые массивы result и statistics;
    • все последующие ответы потока содержат массив result с порцией записей, а также пустые массивы metadata и statistics (см. пример ниже);
  • в Avro-формате:
    • первый ответ потока содержит заголовок со схемой данных Avro (см. пример выше);
    • все последующие ответы потока содержат блоки данных без заголовка и схемы;
  • в plain-формате:
    • первый ответ потока содержит список имен столбцов, присутствующих в выборке;
    • все последующие ответы потока содержат порции записей без метаданных.

Режимы чтения данных

Метод поддерживает следующие режимы чтения данных:

  • однократное чтение — возвращается один ответ с полной выборкой по запросу;
  • потоковое чтение — возвращается поток из множества ответов, содержащих порции данных указанного размера.

По умолчанию метод возвращает результат чтения одним ответом, но, если в теле запроса задан параметр fetchSize, результат чтения возвращается в виде потока.

Потоковое чтение данных по HTTP API доступно только при подключении по протоколу HTTP/2 и чтении из СУБД ADB и (или) ADP. Подробнее см. в разделе Потоковое чтение данных.

URL

{baseUrl}/api/v1/datamarts[/{datamart}]/query[?format={format}[&compressionLevel={level}]]

Параметры:

  • baseUrl — адрес ноды Prostore, состоящий из IP-адреса или доменного имени и номера порта;
  • datamart (опциональный) — имя логической базы данных, используемой по умолчанию;
  • format (опциональный) — формат ответа. Возможные значения:
    • json — JSON-строка (по умолчанию);
    • plain — текстовое представление;
    • avro — Avro-формат без сжатия;
    • avro-deflate — Avro-формат со сжатием по алгоритму Deflate;
    • avro-snappy — Avro-формат со сжатием по алгоритму Snappy;
    • avro-bzip2 — Avro-формат со сжатием по алгоритму BZip2;
    • avro-xz — Avro-формат со сжатием по алгоритму XZ;
    • avro-zstanstard — Avro-формат со сжатием по алгоритму Zstandard;
  • compressionLevel — коэффициент сжатия данных. Должен быть указан для всех перечисленных выше Avro-форматов, кроме avro. Возможные значения коэффициента зависят от выбранного алгоритма сжатия; подробнее см. в документации Apache Avro.

Заголовки запроса

Поддерживаются опциональные заголовки:

  • x-request-id — задает уникальный идентификатор HTTP-запроса. Если не указан, система генерирует UUID-значение и возвращает его в качестве идентификатора в ответе;
  • Authorization — задает тип аутентификации и авторизационный токен (JWT). Возможное значение типа аутентификации — Bearer.

Подробнее об аутентификации запросов см. в разделе Аутентификация.

В асинхронных запросах x-request-id имеет ограничения на символы, описанные в секции ниже.

Ограничения x-request-id

В идентификаторах x-request-id асинхронных запросов не поддерживаются следующие символы (подробнее см. в документации ZooKeeper):

  • точка или две точки без добавления других символов;
  • спецсимволы Unicode;
  • строка zookeeper без добавления других символов.

Тело запроса

Тело запроса может содержать параметры, описанные ниже. В квадратных скобках [ parameter ] отмечены опциональные параметры.

query

Запрос SQL+ из числа поддерживаемых. В простом запросе указывайте значения как есть, в подготовленном — замените каждое значение на символ ?.

[ queryId ]

Идентификатор запроса SQL+. Позволяет отследить обработку запроса с помощью логов.

[ maxRowsToRead ]

Максимальное количество строк, возвращаемых по запросу. При потоковом чтении данных значение применяется к запросу в целом, а не к отдельной порции данных.
Если параметр не задан или его значение равно 0 или null, количество возвращаемых записей не ограничено.

[ fetchSize ]

Максимальное количество записей в порции данных, возвращаемой в одном ответе при потоковом чтении.
Если параметр не задан или его значение равно 0 или null, все записи возвращаются одним ответом со всеми данными выборки (потоковое чтение выключено).

Потоковое чтение по HTTP API доступно только при подключении по протоколу HTTP/2 и чтении из СУБД ADB и (или) ADP. Подробнее см. в разделе Потоковое чтение данных.

Потоковое чтение данных недоступно в асинхронном режиме обработки запроса. При наличии в запросе параметра async со значением true и параметра fetchSize со значением больше 0 учитывается только параметр async — система выполняет запрос в асинхронном режиме и возвращает один ответ, сообщающий о начале обработки запроса (см. пример ниже).

[ fetchTimeoutMs ]

Максимальное время (в миллисекундах) выполнения запроса с учетом всех порций данных, по истечении которого система закрывает соединение с HTTP-клиентом.
Параметр применяется только при потоковом чтении данных. Если он не задан или его значение равно 0 или null, то время выполнения запроса не ограничено.

[ params ]

Список параметров подготовленного запроса:

async

Режим выполнения запроса. Возможные значения:

  • false (по умолчанию) — синхронный режим выполнения;
  • true — асинхронный режим выполнения.

Примеры запросов

В этой секции приведены примеры как с авторизационным токеном, так и без него. Примеры без токена предназначены для случаев, когда аутентификация отключена, с токеном — для случаев, когда аутентификация включена.

Чтение данных одной порцией

Запрос без авторизационного токена:

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/query?format=json' \
  -H 'x-request-id: ee7c7570-1eec-11ed-861d-0242ac120002' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "SELECT st.id, st.category, s.product_code FROM marketing.stores AS st INNER JOIN marketing_new.sales AS s ON st.id = s.store_id DATASOURCE_TYPE = '\''adb'\''",
  "queryId": "12345",
  "maxRowsToRead": 100
}'

Запрос с авторизационным токеном:

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/query?format=json' \
  -H 'x-request-id: ee7c7570-1eec-11ed-861d-0242ac120002' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' \
  -d '{
  "query": "SELECT st.id, st.category, s.product_code FROM marketing.stores AS st INNER JOIN marketing_new.sales AS s ON st.id = s.store_id DATASOURCE_TYPE = '\''adb'\''",
  "queryId": "12345",
  "maxRowsToRead": 100
}'

Потоковое чтение порциями заданного размера

Потоковое чтение данных в Avro-формате

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/query?format=avro-zstandard&compressionLevel=10' \
  -H 'x-request-id: dabf0e53-ca97-40fb-a97e-ba0b4d3088fa' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "SELECT st.id, st.category, s.product_code FROM marketing.stores AS st INNER JOIN marketing_new.sales AS s ON st.id = s.store_id DATASOURCE_TYPE = '\''adb'\''",
  "queryId": "12345",
  "maxRowsToRead": 1000,
  "fetchSize": 100,
  "fetchTimeoutMs": 60000
}'

Потоковое чтение данных в JSON-формате

Запрос:

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/query?format=json' \
  -H 'x-request-id: 84706c2d-ba4a-4bb5-85e3-a367090f5882' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "SELECT * FROM marketing.sales WHERE store_id = 123",
  "queryId": "72848562",
  "maxRowsToRead": 100,
  "fetchSize": 3
}'

Первый ответ в потоке ответов:

{
  "result": null,
  "metadata": [
    {
      "name": "id",
      "type": "BIGINT",
      "size": null,
      "nullable": false
    },
    {
      "name": "transaction_date",
      "type": "TIMESTAMP",
      "size": 6,
      "nullable": false
    },
    {
      "name": "product_code",
      "type": "VARCHAR",
      "size": 256,
      "nullable": false
    },
    {
      "name": "product_units",
      "type": "BIGINT",
      "size": null,
      "nullable": false
    },
    {
      "name": "store_id",
      "type": "BIGINT",
      "size": null,
      "nullable": false
    },
    {
      "name": "description",
      "type": "VARCHAR",
      "size": 256,
      "nullable": true
    }
  ],
  "rows": null,
  "queryId": "84706c2d-ba4a-4bb5-85e3-a367090f5882",
  "statistics": null
}

Следующий ответ в потоке ответов:

{
  "result": [
    {
      "id": 300123,
      "transaction_date": "2023-08-22 13:17:47",
      "product_code": "ABC0002",
      "product_units": 4,
      "store_id": 123,
      "description": "Покупка по акции \"Лето\""
    },
    {
      "id": 300021,
      "transaction_date": "2023-08-21 23:34:10",
      "product_code": "ABC0001",
      "product_units": 2,
      "store_id": 123,
      "description": "Покупка по акции \"1+1\""
    },
    {
      "id": 300133,
      "transaction_date": "2023-08-23 18:01:04",
      "product_code": "ABC0002",
      "product_units": 4,
      "store_id": 123,
      "description": "Покупка по акции \"Лето\""
    }
  ],
  "metadata": null,
  "rows": null,
  "queryId": null,
  "statistics": null
}

Последний ответ в потоке с остатком записей, который может быть меньше заданного значения fetchSize:

{
  "result": [
    {
      "id": 300031,
      "transaction_date": "2021-08-25 15:34:10",
      "product_code": "ABC0001",
      "product_units": 2,
      "store_id": 123,
      "description": "Покупка по акции \"1+1\""
    },
    {
      "id": 11,
      "transaction_date": "2021-09-11 10:23:40",
      "product_code": "ABC0004",
      "product_units": 2,
      "store_id": 123,
      "description": "Покупка по акции \"1+1\""
    }
  ],
  "metadata": null,
  "rows": null,
  "queryId": null,
  "statistics": null
}

Обновление данных в синхронном режиме

Запрос:

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/query?format=json' \
  -H 'x-request-id: 048d4ed9-5fe3-48a2-93a2-fc95885fc037' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "INSERT INTO marketing.sales VALUES (11, '\''2021-07-11 23:34:10'\'', '\''ABC0004'\'', 2, 123, '\''Покупка по акции \"1+1\"'\'')",
  "queryId": "1y3ty4y"
}'

Ответ:

{
  "result": [
    {
      "sysCn": 94
    }
  ],
  "metadata": [
    {
      "name": "sysCn",
      "type": "BIGINT",
      "size": null,
      "nullable": false
    }
  ],
  "rows": 1,
  "queryId": "1y3ty4y",
  "statistics": {
    "elapsedTotalMs": 454,
    "elapsedDbMs": 1105
  }
}

Обновление данных в асинхронном режиме

Запрос:

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/query?format=json' \
  -H 'x-request-id: 4519785b-4a9b-4d3b-b332-a39e5b56ae1d' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "INSERT INTO marketing.sales VALUES (11, '\''2021-07-11 23:34:10'\'', '\''ABC0004'\'', 2, 123, '\''Покупка по акции \"1+1\"'\'')",
  "queryId": "34678765hd6",
  "async": true
}'

Ответ:

{
  "requestId": "4519785b-4a9b-4d3b-b332-a39e5b56ae1d",
  "message": "Async operation started"
}

Подготовленный запрос (prepared statement)

Запрос на обновление данных в синхронном режиме без токена:

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/marketing/query?format=json' \
  -H 'x-request-id: ee7c7570-1eec-11ed-861d-0242ac120002' \
  -H 'Content-Type: application/json' \
  -d '{
  "query": "INSERT INTO sales (id, transaction_date, product_code, product_units, store_id) values (?, ?, ?, ?, ?), (?, ?, ?, ?, ?)",
  "queryId": "98765",
  "params": [
    {
      "value": 300014,
      "type": "INT"
    },
    {
      "value": "2022-08-23 09:34:10",
      "type": "TIMESTAMP"
    },
    {
      "value": "ABC0003",
      "type": "VARCHAR"
    },
    {
      "value": 3,
      "type": "INT"
    },
    {
      "value": 123,
      "type": "INT"
    },
    {
      "value": 300015,
      "type": "INT"
    },
    {
      "value": "2022-08-23 20:05:56",
      "type": "TIMESTAMP"
    },
    {
      "value": "ABC0001",
      "type": "VARCHAR"
    },
    {
      "value": 6,
      "type": "INT"
    },
    {
      "value": 234,
      "type": "INT"
    }
  ]
}'

Запрос на обновление данных в асинхронном режиме с токеном:

curl -X 'POST' \
  'http://localhost:9090/api/v1/datamarts/marketing/query?format=json' \
  -H 'x-request-id: 1f6d3043-4c54-43ca-8653-9bf090a51971' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' \
  -d '{
  "query": "INSERT INTO sales (id, transaction_date, product_code, product_units, store_id) values (?, ?, ?, ?, ?), (?, ?, ?, ?, ?)",
  "queryId": "398775",
  "async": true,
  "params": [
    {
      "value": 300014,
      "type": "INT"
    },
    {
      "value": "2022-08-23 09:34:10",
      "type": "TIMESTAMP"
    },
    {
      "value": "ABC0003",
      "type": "VARCHAR"
    },
    {
      "value": 3,
      "type": "INT"
    },
    {
      "value": 123,
      "type": "INT"
    },
    {
      "value": 300015,
      "type": "INT"
    },
    {
      "value": "2022-08-23 20:05:56",
      "type": "TIMESTAMP"
    },
    {
      "value": "ABC0001",
      "type": "VARCHAR"
    },
    {
      "value": 6,
      "type": "INT"
    },
    {
      "value": 234,
      "type": "INT"
    }
  ]
}'