mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
New ?_sql_time_limit_ms=10 argument to database and table page
Allows callers to opt for a lower time limit. Closes #95
This commit is contained in:
parent
0b8c1b0a6d
commit
9cb69cbd45
2 changed files with 31 additions and 4 deletions
|
|
@ -114,7 +114,7 @@ class BaseView(HTTPMethodView):
|
|||
for name, num_args, func in self.ds.sqlite_functions:
|
||||
conn.create_function(name, num_args, func)
|
||||
|
||||
async def execute(self, db_name, sql, params=None, truncate=False):
|
||||
async def execute(self, db_name, sql, params=None, truncate=False, custom_time_limit=None):
|
||||
"""Executes sql against db_name in a thread"""
|
||||
def sql_operation_in_thread():
|
||||
conn = getattr(connections, db_name, None)
|
||||
|
|
@ -128,7 +128,11 @@ class BaseView(HTTPMethodView):
|
|||
self.prepare_connection(conn)
|
||||
setattr(connections, db_name, conn)
|
||||
|
||||
with sqlite_timelimit(conn, self.ds.sql_time_limit_ms):
|
||||
time_limit_ms = self.ds.sql_time_limit_ms
|
||||
if custom_time_limit and custom_time_limit < self.ds.sql_time_limit_ms:
|
||||
time_limit_ms = custom_time_limit
|
||||
|
||||
with sqlite_timelimit(conn, time_limit_ms):
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(sql, params or {})
|
||||
|
|
@ -312,7 +316,12 @@ class DatabaseView(BaseView):
|
|||
params = request.raw_args
|
||||
sql = params.pop('sql')
|
||||
validate_sql_select(sql)
|
||||
rows, truncated, description = await self.execute(name, sql, params, truncate=True)
|
||||
extra_args = {}
|
||||
if params.get('_sql_time_limit_ms'):
|
||||
extra_args['custom_time_limit'] = int(params['_sql_time_limit_ms'])
|
||||
rows, truncated, description = await self.execute(
|
||||
name, sql, params, truncate=True, **extra_args
|
||||
)
|
||||
columns = [r[0] for r in description]
|
||||
return {
|
||||
'database': name,
|
||||
|
|
@ -428,7 +437,13 @@ class TableView(BaseView):
|
|||
offset=offset,
|
||||
)
|
||||
|
||||
rows, truncated, description = await self.execute(name, sql, params, truncate=True)
|
||||
extra_args = {}
|
||||
if request.raw_args.get('_sql_time_limit_ms'):
|
||||
extra_args['custom_time_limit'] = int(request.raw_args['_sql_time_limit_ms'])
|
||||
|
||||
rows, truncated, description = await self.execute(
|
||||
name, sql, params, truncate=True, **extra_args
|
||||
)
|
||||
|
||||
columns = [r[0] for r in description]
|
||||
display_columns = columns
|
||||
|
|
|
|||
|
|
@ -101,6 +101,18 @@ def test_sql_time_limit(app_client):
|
|||
assert 'interrupted' == response.json['error']
|
||||
|
||||
|
||||
def test_custom_sql_time_limit(app_client):
|
||||
_, response = app_client.get(
|
||||
'/test_tables.jsono?sql=select+sleep(0.01)'
|
||||
)
|
||||
assert 200 == response.status
|
||||
_, response = app_client.get(
|
||||
'/test_tables.jsono?sql=select+sleep(0.01)&_sql_time_limit_ms=5'
|
||||
)
|
||||
assert 400 == response.status
|
||||
assert 'interrupted' == response.json['error']
|
||||
|
||||
|
||||
def test_invalid_custom_sql(app_client):
|
||||
_, response = app_client.get(
|
||||
'/test_tables?sql=.schema'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue