Skip to content

ClickHouse Rewrite API

Use POST /v1/rewrite/clickhouse only when your app still wants to send the final ClickHouse HTTP request itself.

Most users should start with the simpler ClickHouse API instead.

Replace SQLTAMER_BASE_URL with your API base URL before running the examples on this page.

Minimal request

curl -X POST "$SQLTAMER_BASE_URL/v1/rewrite/clickhouse" \
  -H "Authorization: Bearer $SQLTAMER_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "sql": "SELECT count() FROM events WHERE user_id IN (101, 909, 4201, 9907, 12003, 15055)",
    "min_in_list_items": 3
  }'

Accepted overrides on this endpoint are ClickHouse-specific only:

  • min_in_list_items
  • enable_dense_integer_in_list_compression
  • enable_in_list_to_any_array Leave this off unless you specifically want typed ClickHouse query params for medium-size lists. The server default policy keeps it off and prefers dense compression plus external-table uploads.
  • enable_in_list_to_temp_table
  • enable_case_to_temp_table
  • enable_nested_case_to_temp_table
  • rules for the supported ClickHouse rewrite set

Insert-splitting controls such as enable_insert_values_split, max_insert_rows_per_statement, and max_insert_sql_bytes are not accepted here.

What comes back

  • rewritten: whether a rewrite was applied
  • http_request.query_params: query string values to send to ClickHouse
  • http_request.multipart_form_fields: external-table uploads when needed
  • metadata.applied_rewrites: which rule fired

This endpoint returns a prepared ClickHouse request shape. It does not forward the request upstream for you.

Two response shapes

Query params only

Compatible medium-size lists can come back as typed ClickHouse params when you opt in:

{
  "rewritten": true,
  "http_request": {
    "query_params": {
      "query": "SELECT count() FROM events WHERE user_id IN ({sqltamer_param_1:Array(Int64)})",
      "param_sqltamer_param_1": "[101, 909, 4201, 9907, 12003, 15055]"
    },
    "multipart_form_fields": []
  }
}

External table upload

Very large lists can come back as query params plus multipart fields:

{
  "rewritten": true,
  "http_request": {
    "query_params": {
      "query": "SELECT count() FROM events WHERE user_id IN (SELECT value FROM temp_sqltamer_in_1)",
      "temp_sqltamer_in_1_format": "TabSeparated",
      "temp_sqltamer_in_1_structure": "value Int64"
    },
    "multipart_form_fields": [
      {
        "name": "temp_sqltamer_in_1",
        "content_type": "text/tab-separated-values"
      }
    ]
  }
}

CASE rewrites stay inside http_request.query_params.query. On ClickHouse they become transform(...).

How to send the result

  1. Start with your normal ClickHouse HTTP URL.
  2. Merge in http_request.query_params.
  3. If multipart_form_fields is empty, send a normal POST.
  4. If multipart_form_fields is present, send multipart/form-data and include each returned field exactly as provided.

Supported rewrites

  • dense_integer_in_list_compression
  • in_list_to_any_array
  • in_list_to_temp_table
  • case_to_temp_table
  • nested_case_to_temp_table

insert_values_split is not supported on the ClickHouse path.

Notes

  • rewritten=false is normal and still returns a usable request shape
  • multipart_form_fields[].body is already the TSV payload to send
  • The endpoint currently supports one SELECT or WITH statement per request