diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index 44641a87..70ac8976 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -1080,11 +1080,12 @@ class StartupError(Exception): _re_named_parameter = re.compile(":([a-zA-Z0-9_]+)") + async def derive_named_parameters(db, sql): - explain = 'explain {}'.format(sql.strip().rstrip(";")) + explain = "explain {}".format(sql.strip().rstrip(";")) possible_params = _re_named_parameter.findall(sql) try: results = await db.execute(explain, {p: None for p in possible_params}) return [row["p4"].lstrip(":") for row in results if row["opcode"] == "Variable"] except sqlite3.DatabaseError: - return [] + return possible_params diff --git a/tests/test_utils.py b/tests/test_utils.py index e04efb4b..e1b61072 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -629,13 +629,16 @@ def test_parse_metadata(content, expected): @pytest.mark.asyncio -@pytest.mark.parametrize("sql,expected", ( - ("select 1", []), - ("select 1 + :one", ["one"]), - ("select 1 + :one + :two", ["one", "two"]), - ("select 'bob' || '0:00' || :cat", ["cat"]), - ("select this is invalid", []), -)) +@pytest.mark.parametrize( + "sql,expected", + ( + ("select 1", []), + ("select 1 + :one", ["one"]), + ("select 1 + :one + :two", ["one", "two"]), + ("select 'bob' || '0:00' || :cat", ["cat"]), + ("select this is invalid :one, :two, :three", ["one", "two", "three"]), + ), +) async def test_derive_named_parameters(sql, expected): ds = Datasette([], memory=True) db = ds.get_database("_memory")