Skip to content

SQL Queries

GlueSQL against a ProllyTree store. Tables are persisted in the tree, so every write is versioned — git-prolly commit, branch, merge work exactly as with raw KV.

See SQL Interface for the full surface and limitations.

CLI

git-prolly sql "CREATE TABLE users (id INTEGER, name TEXT, email TEXT)"
git-prolly sql "INSERT INTO users VALUES (1, 'Alice', 'alice@example.com'),
                                          (2, 'Bob',   'bob@example.com')"
git-prolly sql "SELECT * FROM users ORDER BY id"

# Commit the changes.
git-prolly commit -m "seed users"

Read-only queries against history

git-prolly sql -b v1.0   "SELECT COUNT(*) FROM users"
git-prolly sql -b main   "SELECT * FROM users WHERE id = 42"
git-prolly sql -b feat   "SELECT name FROM users WHERE created_at > '2024-01-01'"

Write statements (INSERT/UPDATE/DELETE/CREATE) are rejected with -b. Switch branches if you want to modify.

Output formats

git-prolly sql -o table "SELECT * FROM users"   # pretty (default)
git-prolly sql -o json  "SELECT * FROM users"   # machine readable
git-prolly sql -o csv   "SELECT * FROM users"   # spreadsheet-friendly

File-driven workflow

cat > schema.sql <<'EOF'
CREATE TABLE products (
    id INTEGER, name TEXT, price INTEGER, category TEXT
);
INSERT INTO products VALUES
    (1, 'Laptop', 1200, 'Electronics'),
    (2, 'Book',     25, 'Education');
EOF

git-prolly sql -f schema.sql
git-prolly commit -m "initial schema"

Interactive shell

git-prolly sql -i
# prolly-sql> CREATE TABLE foo (id INTEGER);
# prolly-sql> SELECT * FROM foo;
# prolly-sql> exit

Python

from prollytree import ProllySQLStore

sql = ProllySQLStore("./store")

sql.execute("""
    CREATE TABLE users (
        id INTEGER,
        name TEXT,
        email TEXT,
        signup_date TEXT,
        plan TEXT
    )
""")

sql.execute(
    "INSERT INTO users VALUES (?, ?, ?, ?, ?)",
    (1, "Alice", "alice@example.com", "2024-01-15", "premium"),
)

# Analytics.
rows = sql.execute("""
    SELECT plan, COUNT(*) AS cnt
    FROM users
    GROUP BY plan
    ORDER BY cnt DESC
""")
for r in rows:
    print(r)

Combining SQL with versioning

SQL writes are ordinary tree writes — you commit them with the same commit() you use for raw KV:

from prollytree import VersionedKvStore, ProllySQLStore

kv  = VersionedKvStore("./store")
sql = ProllySQLStore.from_store(kv)                # shared store

sql.execute("CREATE TABLE audit (actor TEXT, action TEXT, ts TEXT)")
sql.execute("INSERT INTO audit VALUES ('alice', 'login', '2024-01-15T09:00:00')")
kv.commit("initial audit")

# Now audit lives on main branch; branching off 'experiment' isolates writes.
kv.create_branch("experiment")
sql.execute("INSERT INTO audit VALUES ('alice', 'test', '2024-01-15T09:05:00')")
kv.commit("experimental entry")

This is the pattern behind branch-scoped data migrations and A/B testing — see Versioning & Merge.