db.execute_write(executescript=True) option, closes #1569

pull/1589/head
Simon Willison 2021-12-18 10:28:25 -08:00
rodzic 85c22f4fbc
commit 9e094b7c9d
3 zmienionych plików z 31 dodań i 4 usunięć

Wyświetl plik

@ -94,10 +94,14 @@ class Database:
f"file:{self.path}{qs}", uri=True, check_same_thread=False
)
async def execute_write(self, sql, params=None, block=False):
async def execute_write(self, sql, params=None, executescript=False, block=False):
assert not (executescript and params), "Cannot use params with executescript=True"
def _inner(conn):
with conn:
return conn.execute(sql, params or [])
if executescript:
return conn.executescript(sql)
else:
return conn.execute(sql, params or [])
with trace("sql", database=self.name, sql=sql.strip(), params=params):
results = await self.execute_write_fn(_inner, block=block)

Wyświetl plik

@ -663,8 +663,8 @@ Example usage:
.. _database_execute_write:
await db.execute_write(sql, params=None, block=False)
-----------------------------------------------------
await db.execute_write(sql, params=None, executescript=False, block=False)
--------------------------------------------------------------------------
SQLite only allows one database connection to write at a time. Datasette handles this for you by maintaining a queue of writes to be executed against a given database. Plugins can submit write operations to this queue and they will be executed in the order in which they are received.
@ -676,6 +676,8 @@ By default queries are considered to be "fire and forget" - they will be added t
If you pass ``block=True`` this behaviour changes: the method will block until the write operation has completed, and the return value will be the return from calling ``conn.execute(...)`` using the underlying ``sqlite3`` Python library.
If you pass ``executescript=True`` your SQL will be executed using the ``sqlite3`` `conn.executescript() <https://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor.executescript>`__ method. This allows multiple SQL statements to be separated by semicolons, but cannot be used with the ``params=`` option.
.. _database_execute_write_fn:
await db.execute_write_fn(fn, block=False)

Wyświetl plik

@ -396,6 +396,27 @@ async def test_execute_write_block_false(db):
assert "Mystery!" == rows.rows[0][0]
@pytest.mark.asyncio
async def test_execute_write_executescript(db):
await db.execute_write(
"create table foo (id integer primary key); create table bar (id integer primary key); ",
executescript=True,
block=True
)
table_names = await db.table_names()
assert {"foo", "bar"}.issubset(table_names)
@pytest.mark.asyncio
async def test_execute_write_executescript_not_allowed_with_params(db):
with pytest.raises(AssertionError):
await db.execute_write(
"update roadside_attractions set name = ? where pk = ?",
["Mystery!", 1],
executescript=True
)
@pytest.mark.asyncio
async def test_execute_write_has_correctly_prepared_connection(db):
# The sleep() function is only available if ds._prepare_connection() was called