Day 84: SQL and Warehouse Copilots

Day 84: SQL and Warehouse Copilots

Warehouse copilots that can DROP or scan-billions-without-EXPLAIN will get you a FinOps incident and a security review. Default read-only; plan before run; cap bytes scanned.

⚡ TL;DR: Separate author (LLM) from runner (SQL gateway). Allowlist tables. EXPLAIN/dry_run first. Hard cap on scanned bytes and runtime. Log every statement with user id.

Safe execution loop

# ✅ Author → validate → explain → optional run
FORBIDDEN = {"drop", "delete", "update", "insert", "alter", "grant"}

def run_copilot_sql(sql: str, *, user: str, dry_run: bool = True):
    ast = parse_sql(sql)
    if any(n in FORBIDDEN for n in ast.verbs):
        raise PermissionError("mutating SQL blocked")
    if not tables_allowlisted(ast.tables, user):
        raise PermissionError("table not allowlisted")
    plan = explain(sql)
    if plan.bytes_scanned > 50_000_000_000:  # 50GB
        raise PermissionError("scan too large")
    if dry_run:
        return {"plan": plan, "rows": None}
    return {"plan": plan, "rows": execute_readonly(sql, timeout_s=30)}
Control Setting
Role Read-only warehouse user
Timeout 30–60s interactive
Row cap 10k preview
Audit statement + user + cost

❌ Giving the model the same credentials as the analytics engineer’s admin role.

Failure modes

SELECT * on semi-structured JSON columns that explodes bytes scanned. Template library of approved query shapes helps. LLMs that rewrite LIMIT away — AST rewrite to re-inject caps after generation.

Closing checklist

  • [ ] Read-only role + allowlisted datasets
  • [ ] EXPLAIN/dry-run path mandatory in UI
  • [ ] Bytes-scanned guardrail
  • [ ] Statement audit log
  • [ ] Eval: hostile prompts trying DDL

Series navigation

Day 83: Multimodal Coding: Screenshots of Broken UIs · Day 85: Time-Series and Anomaly Copilots

Last updated September 11, 2026


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply