SQL Tamer

SQL Rewrite

Rewrite oversized SQL so it runs again.

SQL Tamer takes giant IN lists, large CASE expressions, and other oversized queries and rewrites them into shapes your database can execute. On supported patterns, it can also speed them up.

The fastest hosted path today is the CLI plus ClickHouse proxy flow: create auth once, add a destination, and point your client at the returned proxy URL.

Unlimited rewrites in preview Measured up to 15.8x faster Postgres API + ClickHouse proxy

Install CLI

Install SQL Tamer with one command.

The hosted installer detects macOS or Linux x86_64, downloads the latest CLI bundle, and puts sqltamer in ~/.local/bin by default.

Current website build: CLI v0.1.0

curl -fsSL https://sqltamer.com/install.sh | sh

Quick Start

Try the ClickHouse proxy in three steps.

If your app already sends ClickHouse over HTTP, you can test SQL Tamer without changing your query flow: create auth, add a destination, then swap in the proxy URL.

Step 1 Run sqltamer auth init once to create preview access and save the API key locally.
Step 2 Create a ClickHouse destination with sqltamer clickhouse add.
Step 3 Send the same ClickHouse HTTP request to the returned proxy URL and compare the result.

SQL Examples

See how SQL Tamer changes the query.

Each example shows the original SQL, the rewritten shape, and the sample benchmark result for that pattern.

Dense integer list

Replace a long adjacent IN list with a range

When the ids are consecutive, SQL Tamer can collapse the list before Postgres plans the query.

Input SQL Original oversized query
SELECT COUNT(*)
FROM benchmark_items
WHERE id IN (100001, 100002, 100003, 100004, 100005, 100006);
Rewritten query Shorter SQL, same filter
SELECT COUNT(*)
FROM benchmark_items
WHERE id BETWEEN 100001 AND 100006;

Best case: one long run becomes one range check.

Measured benchmark 126.8 ms -> 8.0 ms

15.8x faster

Sparse bigint list

Replace a huge sparse IN list with one array parameter

Instead of pasting thousands of literals into the SQL string, SQL Tamer sends the ids separately as one BIGINT[] bind.

Input SQL Original oversized query
SELECT id, email
FROM users
WHERE id IN (101, 909, 4201, 9907, 12003, 15055);
Rewritten query Shorter SQL with bound data
SELECT id, email
FROM users
WHERE id = ANY($1::BIGINT[]);
Parameter values Sent separately from the SQL text
$1 = [101, 909, 4201, 9907, 12003, 15055]

Your app keeps the data out of the SQL text and sends it as one parameter.

Measured benchmark 110.0 ms -> 24.9 ms

4.4x faster

Large CASE map

Turn a giant CASE block into lookup data

When a CASE expression is really a mapping table, SQL Tamer can stage that data once and join against it.

Input SQL Original oversized query
SELECT COUNT(*)
FROM subscriptions
WHERE CASE
  WHEN country = 'country_1' AND plan = 'plan_1' THEN 'label_1'
  WHEN plan = 'plan_2' AND country = 'country_2' THEN 'label_2'
  ELSE 'other'
END <> 'other';
Rewritten flow Load lookup data once, then run the main query
CREATE TEMP TABLE temp_sqltamer_case_1 (...);
CREATE INDEX ON temp_sqltamer_case_1 (country, plan);
-- load the lookup rows once

SELECT COUNT(*)
FROM subscriptions AS s
LEFT JOIN temp_sqltamer_case_1 AS map
  ON map.country = s.country
 AND map.plan = s.plan
WHERE COALESCE(map.value, 'other') <> 'other';

In practice, SQL Tamer turns the CASE map into temporary lookup data, runs the query, then cleans up.

Measured benchmark 2601.2 ms -> 363.8 ms

7.1x faster

Implementation

Need request formats or client examples?

The docs cover the rewrite API, the ClickHouse proxy flow, sample requests, and the benchmark methodology behind the numbers above.

Try It

Test it with one of your own queries.

Start with the CLI guide, add one destination, and compare the proxy response against the query your application sends today.