Skip to main content

iceql

日本語版 README

A local RDBMS with plaintext storage (CSV + YAML). Like SQLite, a database is self-contained and queryable with SQL — but the storage stays human-readable.

SQLite database files are binary, so you cannot hand one to an LLM and have it read the contents directly. iceql stores tables as CSV and schemas as YAML, so both LLMs and humans can read the storage as-is. Writes always produce a canonical form (LF newlines, minimal quoting, one record per line), which keeps git diffs clean and meaningful.

Installation

$ uv tool install iceql   # as a CLI
$ uv add iceql            # as a library

Quick start

A database is just a directory.

$ iceql mydb -c "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER)"
$ iceql mydb -c "INSERT INTO users VALUES (1, 'alice', 30), (2, 'bob', NULL)"
$ iceql mydb -c "SELECT * FROM users WHERE age IS NULL"
id,name,age
2,bob,\N

The resulting files are readable as-is.

$ cat mydb/users.csv
id,name,age
1,alice,30
2,bob,\N
$ cat mydb/users.schema.yaml
version: 1
table: users
columns:
- name: id
  type: integer
  nullable: false
  primary_key: true
- name: name
  type: text
  nullable: false
- name: age
  type: integer
  nullable: true
null_marker: \N

Running without arguments opens a psql-style REPL.

$ iceql mydb
iceql (0.1.1)
Type "\?" for help.
mydb=# SELECT COUNT(*) FROM users;
_col_0
------
2
mydb=# \d
List of tables
  users
mydb=# \x
Expanded display is on.
mydb=# SELECT * FROM users;
-[ RECORD 1 ]-
id   | 1
name | alice
age  | 30
-[ RECORD 2 ]-
id   | 2
name | bob
age  |
mydb=# \q

Meta commands: \d [table] (list / describe tables), \x (toggle expanded output), \pset format table|csv|json, \? (help), and \q (quit).

-f table|csv|json selects the output format (defaults to table on a TTY, csv when piped). iceql check mydb validates schema/CSV consistency (types, NOT NULL, duplicate primary keys, canonical form) and exits non-zero on errors. This makes hand-edited CSV files verifiable in CI or a pre-commit hook.

Python API

A DB-API 2.0 style API, familiar to anyone who has used the sqlite3 module.

import iceql

conn = iceql.connect("mydb")
conn.execute("INSERT INTO users VALUES (?, ?, ?)", (3, "carol", 25))
for row in conn.execute("SELECT name FROM users WHERE age > :min", {"min": 20}):
    print(row)
conn.close()

Supported SQL

  • SELECT: WHERE, JOIN (INNER / LEFT), GROUP BY, aggregate functions, HAVING, ORDER BY (with NULLS FIRST / LAST), LIMIT / OFFSET, DISTINCT, IN subqueries, CTE (WITH), UNION / UNION ALL
  • DML: INSERT (VALUES / SELECT), UPDATE, DELETE
  • DDL: CREATE TABLE, DROP TABLE, ALTER TABLE (ADD / DROP / RENAME COLUMN, RENAME TO)
  • Transactions: BEGIN / COMMIT / ROLLBACK (changes are staged in memory and flushed on COMMIT; DDL is not allowed inside a transaction)
  • Placeholders: ? (qmark) and :name (named)

SQL parsing and SELECT execution are powered by sqlglot. NULL ordering follows the SQLite default (NULL sorts smallest: first in ASC, last in DESC).

Types

Type CSV representation
integer decimal integer
real floating point (shortest round-trip form)
boolean true / false
text string (quoted only when it contains , " or newlines)
date YYYY-MM-DD
datetime ISO-8601

NULL is represented as an unquoted \N (the same convention as PostgreSQL COPY). An empty string is an empty field, so NULL and the empty string are distinguishable. A literal string \N is escaped as \\N.

MCP server

A built-in MCP server lets LLM agents read and write the database directly.

$ uv tool install 'iceql[mcp]'
$ iceql mcp mydb --read-only   # drop --read-only to enable write tools

Four tools are exposed: query (SELECT only), execute (DML / DDL), list_tables, and describe_table.

Limitations

  • Window functions, DISTINCT inside aggregates (e.g. COUNT(DISTINCT x)), and scalar subqueries in the SELECT list are not supported (they fail with a clear error)
  • Transactions are per-connection with no isolation between connections; a COMMIT touching multiple tables is not atomic
  • Tables are fully loaded into memory at query time; the intended scope is databases small enough for an LLM to read directly (tens of thousands of rows)
  • Windows is not supported (inter-process locking uses fcntl)

Development

$ uv sync --all-groups
$ uv run pytest
$ uv run ruff check src tests
$ uv run mypy

The test suite includes differential tests that run the same queries against both iceql and sqlite3 and compare the results.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

iceql-0.1.2.tar.gz (26.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

iceql-0.1.2-py3-none-any.whl (34.7 kB view details)

Uploaded Python 3

File details

Details for the file iceql-0.1.2.tar.gz.

File metadata

  • Download URL: iceql-0.1.2.tar.gz
  • Upload date:
  • Size: 26.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for iceql-0.1.2.tar.gz
Algorithm Hash digest
SHA256 68e0e75163761dc654a156f63ad8a910a0f1678cb43f981f61518add84c734b1
MD5 0e8e92f76d3b5831baf90ac5af5fd727
BLAKE2b-256 1d5129eead0a80917b8cf701a8e39efed7a61197b976761556b6b761c144dea4

See more details on using hashes here.

File details

Details for the file iceql-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: iceql-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 34.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for iceql-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ade39fdf419784300eb2d84169e304aa1488ce420b04723885289ae0aa7646cb
MD5 e99db33b48520857cc3eb2c6685664e9
BLAKE2b-256 adab6c4e60f5412a39c6b859928818f62df3a2f8412535e1cf1929346c5fc6f2

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.0

2 files

0.2.0

2 files

This release

0.1.2 This release

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page