Skolem compiles both queries to SMT constraints and asks Z3 whether a database exists where they disagree. If one does, you get that database — every row, every NULL.
SELECT u.id, COUNT(o.id) FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.id;
SELECT u.id, COUNT(*) FROM users u JOIN orders o ON o.user_id = u.id GROUP BY u.id;
CREATE TABLE users ( id INT PRIMARY KEY, name TEXT NOT NULL ); CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT NOT NULL REFERENCES users(id), cents INT NOT NULL );
Dialect-aware parse of both queries, plus your Flyway DDL with every ALTER TABLE folded in.
Bag semantics preserved — duplicates are part of the meaning, so multiplicity is compared, not just membership.
Schema, keys and three-valued logic become Z3 assertions. Each cell is an (is_null, value) pair.
Ask for a database where the outputs differ, bounded to k rows per table.
No such database exists within the bound — or here is one, printed as rows you can paste.
Every counterexample is re-run on a real SQLite database. If the outputs agree after all, we report an internal error rather than show you a fake.
The LEFT JOIN → JOIN rewrite drops
users with no orders. Two rows are enough to prove it, and Skolem
hands you those two rows.
| id | name |
|---|---|
| 1 | ada |
| 2 | lin |
| id | user_id | cents |
|---|---|---|
| 10 | 1 | 4900 |
| u.id | count |
|---|---|
| 1 | 1 |
| 2 | 0 |
| u.id | count |
|---|---|
| 1 | 1 |
-- reproduce locally INSERT INTO users VALUES (1, 'ada'), (2, 'lin'); INSERT INTO orders VALUES (10, 1, 4900);
Anything outside the subset raises an error instead of being silently dropped. A skipped predicate would weaken the encoding and could return a false “equivalent” — the one failure mode a verifier must not have.
The workspace, the skolem CLI and
the MCP server all call the same solver. Gate a pull request on
status == "equivalent" and let the
counterexample land in the PR comment.
curl -X POST https://sqlverify.com/api/verify/text \ -H "Authorization: Bearer $SKOLEM_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "ddl_sql": "CREATE TABLE users (...);", "sql_v1": "SELECT ...", "sql_v2": "SELECT ...", "bound": 3 }'
{
"status": "divergent",
"divergence_reason": "row presence differs",
"counterexample_db": {
"users": [[1, "ada"], [2, "lin"]],
"orders": [[10, 1, 4900]]
},
"query_v1_output": [[1, 1], [2, 0]],
"query_v2_output": [[1, 1]],
"explanation": "The rewrite turns the LEFT JOIN…"
}
Free for solo projects and open source. No database credentials required — Skolem only reads your schema and your SQL.