mirror of
https://github.com/simonw/datasette.git
synced 2026-06-13 04:27:00 +02:00
Skip RETURNING tests if SQLite version does not support it
https://github.com/simonw/datasette/pull/2763#issuecomment-4588138314
This commit is contained in:
parent
b4761bab53
commit
58dcedb510
4 changed files with 59 additions and 2 deletions
|
|
@ -13,6 +13,7 @@ if hasattr(sqlite3, "enable_callback_tracebacks"):
|
|||
sqlite3.enable_callback_tracebacks(True)
|
||||
|
||||
_cached_sqlite_version = None
|
||||
_cached_supports_returning = None
|
||||
SQLiteTableType = Literal["table", "view", "virtual", "shadow"]
|
||||
_VIRTUAL_TABLE_MODULE_RE = re.compile(
|
||||
r"\bCREATE\s+VIRTUAL\s+TABLE\b.*?\bUSING\s+([^\s(]+)",
|
||||
|
|
@ -59,6 +60,21 @@ def supports_generated_columns():
|
|||
return sqlite_version() >= (3, 31, 0)
|
||||
|
||||
|
||||
def supports_returning():
|
||||
global _cached_supports_returning
|
||||
if _cached_supports_returning is None:
|
||||
conn = sqlite3.connect(":memory:")
|
||||
try:
|
||||
conn.execute("create table t (id integer primary key)")
|
||||
conn.execute("insert into t default values returning id").fetchone()
|
||||
_cached_supports_returning = True
|
||||
except sqlite3.DatabaseError:
|
||||
_cached_supports_returning = False
|
||||
finally:
|
||||
conn.close()
|
||||
return _cached_supports_returning
|
||||
|
||||
|
||||
def sqlite_table_type(
|
||||
conn,
|
||||
table: str,
|
||||
|
|
|
|||
|
|
@ -8,12 +8,16 @@ from datasette.app import Datasette
|
|||
from datasette.database import Database, ExecuteWriteResult, Results, MultipleValues
|
||||
from datasette.database import DatasetteClosedError
|
||||
from datasette.database import _deliver_write_result
|
||||
from datasette.utils.sqlite import sqlite3
|
||||
from datasette.utils.sqlite import sqlite3, supports_returning
|
||||
from datasette.utils import Column
|
||||
import pytest
|
||||
import time
|
||||
import uuid
|
||||
|
||||
requires_sqlite_returning = pytest.mark.skipif(
|
||||
not supports_returning(), reason="SQLite does not support RETURNING"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db(app_client):
|
||||
|
|
@ -481,6 +485,7 @@ async def test_execute_write_block_true(db):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_with_returning(db):
|
||||
await db.execute_write(
|
||||
"create table write_returning (id integer primary key, name text)"
|
||||
|
|
@ -502,6 +507,7 @@ async def test_execute_write_with_returning(db):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_with_returning_default_limit(db):
|
||||
await db.execute_write(
|
||||
"create table write_returning_limit (id integer primary key)"
|
||||
|
|
@ -524,6 +530,7 @@ async def test_execute_write_with_returning_default_limit(db):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_with_returning_custom_limit(db):
|
||||
await db.execute_write(
|
||||
"create table write_returning_custom (id integer primary key)"
|
||||
|
|
@ -544,6 +551,7 @@ async def test_execute_write_with_returning_custom_limit(db):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_with_returning_exact_default_limit(db):
|
||||
await db.execute_write(
|
||||
"create table write_returning_exact_limit (id integer primary key)"
|
||||
|
|
@ -563,6 +571,7 @@ async def test_execute_write_with_returning_exact_default_limit(db):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_with_returning_one_more_than_default_limit(db):
|
||||
await db.execute_write(
|
||||
"create table write_returning_one_more (id integer primary key)"
|
||||
|
|
@ -582,6 +591,7 @@ async def test_execute_write_with_returning_one_more_than_default_limit(db):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_with_returning_return_all(db):
|
||||
await db.execute_write("create table write_returning_all (id integer primary key)")
|
||||
await db.execute_write_many(
|
||||
|
|
@ -611,6 +621,7 @@ async def test_execute_write_block_false(db):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_with_returning_block_false(db):
|
||||
await db.execute_write(
|
||||
"create table write_returning_block_false (id integer primary key, name text)"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@ from datasette.app import Datasette
|
|||
from datasette.resources import DatabaseResource, QueryResource
|
||||
from datasette.stored_queries import StoredQuery, StoredQueryPage
|
||||
from datasette.utils.asgi import Forbidden
|
||||
from datasette.utils.sqlite import supports_returning
|
||||
|
||||
requires_sqlite_returning = pytest.mark.skipif(
|
||||
not supports_returning(), reason="SQLite does not support RETURNING"
|
||||
)
|
||||
|
||||
|
||||
def _template_option_attributes(html, table):
|
||||
|
|
@ -1891,6 +1896,7 @@ async def test_execute_write_post_requires_database_and_table_permissions():
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_json_includes_returning_rows():
|
||||
ds = Datasette(memory=True, default_deny=True)
|
||||
ds.root_enabled = True
|
||||
|
|
@ -1921,6 +1927,7 @@ async def test_execute_write_json_includes_returning_rows():
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_json_returning_rows_can_be_truncated():
|
||||
ds = Datasette(memory=True, default_deny=True)
|
||||
ds.root_enabled = True
|
||||
|
|
@ -1953,6 +1960,7 @@ async def test_execute_write_json_returning_rows_can_be_truncated():
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_html_displays_returning_rows():
|
||||
ds = Datasette(memory=True, default_deny=True)
|
||||
ds.root_enabled = True
|
||||
|
|
@ -1990,6 +1998,7 @@ async def test_execute_write_html_displays_returning_rows():
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_execute_write_html_returning_rows_can_be_truncated():
|
||||
ds = Datasette(memory=True, default_deny=True)
|
||||
ds.root_enabled = True
|
||||
|
|
@ -3135,6 +3144,7 @@ async def test_user_writable_query_execution_rechecks_table_permissions():
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_stored_write_query_with_returning():
|
||||
ds = Datasette(memory=True, default_deny=True)
|
||||
ds.root_enabled = True
|
||||
|
|
@ -3164,6 +3174,7 @@ async def test_stored_write_query_with_returning():
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@requires_sqlite_returning
|
||||
async def test_stored_write_query_with_truncated_returning_message():
|
||||
ds = Datasette(memory=True, default_deny=True)
|
||||
ds.root_enabled = True
|
||||
|
|
|
|||
|
|
@ -5,7 +5,12 @@ Tests for various datasette helper functions.
|
|||
from datasette.app import Datasette
|
||||
from datasette import utils
|
||||
from datasette.utils.asgi import Request
|
||||
from datasette.utils.sqlite import sqlite3, sqlite_hidden_table_names, sqlite_table_type
|
||||
from datasette.utils.sqlite import (
|
||||
sqlite3,
|
||||
sqlite_hidden_table_names,
|
||||
sqlite_table_type,
|
||||
supports_returning,
|
||||
)
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
|
|
@ -226,6 +231,20 @@ def test_detect_fts_different_table_names(table):
|
|||
conn.close()
|
||||
|
||||
|
||||
def test_supports_returning():
|
||||
conn = utils.sqlite3.connect(":memory:")
|
||||
try:
|
||||
conn.execute("create table t (id integer primary key)")
|
||||
conn.execute("insert into t default values returning id").fetchone()
|
||||
expected = True
|
||||
except sqlite3.DatabaseError:
|
||||
expected = False
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
assert supports_returning() is expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("use_fallback", (False, True))
|
||||
def test_sqlite_table_type_detects_virtual_and_shadow_tables(monkeypatch, use_fallback):
|
||||
if use_fallback:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue