Mapping SQLite result columns back to their source `table.column`

Simon Willison's Blog Tools

Summary

This research explores methods to determine the source table and column for each result column in arbitrary SQLite queries, using SQLite's internal column metadata API accessed via Python's apsw library or a ctypes bridge, with applications for tools like Datasette.

No content available
Original Article
View Cached Full Text

Cached at: 06/14/26, 07:34 AM

# Research: Mapping SQLite result columns back to their source `table.column` Source: [https://simonwillison.net/2026/Jun/13/sqlite-column-provenance/](https://simonwillison.net/2026/Jun/13/sqlite-column-provenance/) [Research](https://simonwillison.net/elsewhere/research/)[Mapping SQLite result columns back to their source \`table\.column\`](https://github.com/simonw/research/tree/main/sqlite-column-provenance#readme)— Determining the source \`table\.column\` for each result column in arbitrary SQLite queries is feasible because SQLite computes this internally and exposes it via its column\-metadata API when compiled with \`SQLITE\_ENABLE\_COLUMN\_METADATA\`\. While Python’s standard \`sqlite3\` module doesn’t surface this information, robust methods exist: using the third\-party \`apsw\` library provides direct access with \`cursor\.description\_full\`, or a pure\-stdlib ctypes bridge \(\`column\_provenance\.py\`\) can retrieve the… It would be neat if arbitrary SQL queries in[Datasette](https://datasette.io/)could be rendered with additional information based on which columns from which tables were included in the results\. To build that, we would need to be able to look at a SQL query like`select users\.name, orders\.total from users join orders on orders\.user\_id = users\.id`and programmatically identify the`table\.column`for each result \- navigating not just joins but also more complex syntax like CTEs\. I decided to set Claude Code \(Opus 4\.8, since Fable is currently[banned by the US government](https://simonwillison.net/2026/Jun/13/us-government-directive-to-suspend-access/)\) on the problem\. It found several promising solutions \- one using[apsw](https://github.com/rogerbinns/apsw), another that uses`ctypes`to access the SQLite`sqlite3\_column\_table\_name\(\)`[C function](https://sqlite.org/c3ref/column_database_name.html)\(which is not otherwise exposed to Python\), and one using clever interrogation of the output of`EXPLAIN`\.

Similar Articles

SQLite Query Result Formatter Demo

Simon Willison's Blog

Interactive WebAssembly-based demo for SQLite Query Result Formatter that allows users to format SQL query results in 20+ styles including tables, CSV, JSON, HTML, and Markdown with real-time adjustments.

SQLite 3.53.0

Simon Willison's Blog

SQLite 3.53.0 releases with significant accumulated improvements including ALTER TABLE constraint modifications, new JSON functions (json_array_insert), and major CLI mode enhancements via a new Query Results Formatter library.

ProSPy: A Profiling-Driven SQL-Python Agentic Framework for Enterprise Text-to-SQL

arXiv cs.CL

ProSPy is a profiling-driven SQL-Python agentic framework for enterprise text-to-SQL that structures reasoning into four stages: automatic profiling, schema pruning, dialect-agnostic SQL interface, and Python-based analysis. It achieves execution accuracies of 60.15% and 60.51% on Spider 2.0-Lite and Spider 2.0-Snow with Claude-4.5-Opus, outperforming strong baselines.