diff --git a/docs/cli.rst b/docs/cli.rst index 6ac2c2d..15e2f3a 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -83,6 +83,11 @@ You can run queries against a temporary in-memory database by passing ``:memory: $ sqlite-utils :memory: "select sqlite_version()" [{"sqlite_version()": "3.29.0"}] +You can load SQLite extension modules using the `--load-extension` option:: + + $ sqlite-utils :memory: "select spatialite_version()" --load-extension=/usr/local/lib/mod_spatialite.dylib + [{"spatialite_version()": "4.3.0a"}] + .. _cli_json_values: Nested JSON values diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index 79a8df0..c61d163 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -719,9 +719,29 @@ def drop_view(path, view): type=(str, str), help="Named :parameters for SQL query", ) -def query(path, sql, nl, arrays, csv, no_headers, table, fmt, json_cols, raw, param): +@click.option( + "--load-extension", multiple=True, help="SQLite extensions to load", +) +def query( + path, + sql, + nl, + arrays, + csv, + no_headers, + table, + fmt, + json_cols, + raw, + param, + load_extension, +): "Execute SQL query and return the results as JSON" db = sqlite_utils.Database(path) + if load_extension: + db.conn.enable_load_extension(True) + for ext in load_extension: + db.conn.load_extension(ext) with db.conn: cursor = db.conn.execute(sql, dict(param)) if cursor.description is None: diff --git a/tests/test_cli.py b/tests/test_cli.py index fea89dd..71a2503 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -4,7 +4,7 @@ from click.testing import CliRunner import json import os import pytest -from sqlite_utils.utils import sqlite3 +from sqlite_utils.utils import sqlite3, find_spatialite from .utils import collapse_whitespace @@ -885,6 +885,29 @@ def test_query_raw(db_path, content, is_binary): assert result.output == str(content) +@pytest.mark.skipif(not find_spatialite(), reason="Could not find SpatiaLite extension") +@pytest.mark.skipif( + not hasattr(sqlite3.Connection, "enable_load_extension"), + reason="sqlite3.Connection missing enable_load_extension", +) +def test_query_load_extension(): + # Without --load-extension: + result = CliRunner().invoke(cli.cli, [":memory:", "select spatialite_version()"]) + assert result.exit_code == 1 + assert "no such function: spatialite_version" in repr(result) + # With --load-extension: + result = CliRunner().invoke( + cli.cli, + [ + ":memory:", + "select spatialite_version()", + "--load-extension={}".format(find_spatialite()), + ], + ) + assert result.exit_code == 0, result.stdout + assert ["spatialite_version()"] == list(json.loads(result.output)[0].keys()) + + def test_query_memory_does_not_create_file(tmpdir): owd = os.getcwd() try: