sqlite-utils query - to read SQL from stdin, closes #765

This commit is contained in:
Simon Willison 2026-07-07 17:52:26 -07:00
commit 619770bf42
5 changed files with 48 additions and 0 deletions

View file

@ -4,6 +4,13 @@
Changelog
===========
.. _v_unreleased:
Unreleased
----------
- ``sqlite-utils query`` can now read the SQL query from standard input by passing ``-`` in place of the query, for example ``echo "select * from dogs" | sqlite-utils query dogs.db -``. (:issue:`765`)
.. _v4_0:
4.0 (2026-07-07)

View file

@ -109,6 +109,10 @@ See :ref:`cli_query`.
"select * from chickens where age > :age" \
-p age 1
Pass "-" as the SQL to read the query from standard input:
echo "select * from chickens" | sqlite-utils data.db -
Options:
--attach <TEXT FILE>... Additional databases to attach - specify alias and
filepath

View file

@ -29,6 +29,16 @@ The ``sqlite-utils query`` command lets you run queries directly against a SQLit
.. note::
In Python: :ref:`db.query() <python_api_query>` CLI reference: :ref:`sqlite-utils query <cli_ref_query>`
Pass ``-`` as the SQL query to read the query from standard input. This is useful for longer queries that would otherwise require careful shell escaping, or for piping in SQL generated by another tool:
.. code-block:: bash
echo "select * from dogs" | sqlite-utils query dogs.db -
.. code-block:: bash
sqlite-utils query dogs.db - < query.sql
.. _cli_query_json:
Returning JSON

View file

@ -1893,7 +1893,15 @@ def query(
sqlite-utils data.db \\
"select * from chickens where age > :age" \\
-p age 1
Pass "-" as the SQL to read the query from standard input:
\b
echo "select * from chickens" | sqlite-utils data.db -
"""
if sql == "-":
# Read SQL from standard input
sql = sys.stdin.read()
db = sqlite_utils.Database(path)
_register_db_for_cleanup(db)
for alias, attach_path in attach:

View file

@ -782,6 +782,25 @@ def test_query_json(db_path, sql, args, expected):
assert expected == result.output.strip()
def test_query_sql_from_stdin(db_path):
# https://github.com/simonw/sqlite-utils/issues/765
db = Database(db_path)
with db.conn:
db["dogs"].insert_all(
[
{"id": 1, "age": 4, "name": "Cleo"},
{"id": 2, "age": 2, "name": "Pancakes"},
]
)
result = CliRunner().invoke(
cli.cli,
["query", db_path, "-"],
input="select name from dogs order by name",
)
assert result.exit_code == 0, result.output
assert json.loads(result.output) == [{"name": "Cleo"}, {"name": "Pancakes"}]
def test_query_json_empty(db_path):
result = CliRunner().invoke(
cli.cli,