mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 21:26:39 +00:00
65 lines
3.0 KiB
Python
65 lines
3.0 KiB
Python
"""Execute integer predicates against JSON values, including oversized numbers."""
|
|
|
|
import json
|
|
import os
|
|
|
|
import pytest
|
|
from sqlalchemy import JSON, Column, MetaData, String, Table, select, text
|
|
from sqlalchemy.ext.asyncio import create_async_engine
|
|
|
|
from deerflow.persistence.json_compat import json_match
|
|
|
|
|
|
@pytest.fixture(params=["sqlite", "postgresql"])
|
|
async def json_table(request):
|
|
if request.param == "postgresql":
|
|
url = os.getenv("DEERFLOW_TEST_POSTGRES_URL")
|
|
if not url:
|
|
pytest.skip("set DEERFLOW_TEST_POSTGRES_URL to exercise real PostgreSQL integer matching")
|
|
if url.startswith("postgresql://"):
|
|
url = url.replace("postgresql://", "postgresql+asyncpg://", 1)
|
|
else:
|
|
url = "sqlite+aiosqlite:///:memory:"
|
|
|
|
engine = create_async_engine(url)
|
|
# A connection-local table keeps opt-in PostgreSQL runs isolated from any
|
|
# application schema and is discarded even when an assertion fails.
|
|
table = Table("json_integer_matching", MetaData(), Column("id", String), Column("data", JSON), prefixes=["TEMPORARY"])
|
|
try:
|
|
async with engine.connect() as connection:
|
|
async with connection.begin():
|
|
await connection.run_sync(table.create)
|
|
yield connection, table
|
|
finally:
|
|
await engine.dispose()
|
|
|
|
|
|
@pytest.mark.anyio
|
|
@pytest.mark.parametrize("expected", [-(2**63), -(2**63) + 1, -42, -1, 0, 1, 42, 2**63 - 2, 2**63 - 1])
|
|
async def test_integer_filter_ignores_unrepresentable_stored_numbers(json_table, expected):
|
|
connection, table = json_table
|
|
integers = [-(2**63), -(2**63) + 1, -42, -1, 0, 1, 42, 2**63 - 2, 2**63 - 1]
|
|
rows = [{"id": str(value), "data": json.dumps({"x": value})} for value in integers]
|
|
rows += [
|
|
{"id": "below-min", "data": json.dumps({"x": -(2**63) - 1})},
|
|
{"id": "above-max", "data": json.dumps({"x": 2**63})},
|
|
{"id": "large-negative", "data": json.dumps({"x": -(10**100)})},
|
|
{"id": "large-positive", "data": json.dumps({"x": 10**100})},
|
|
# PostgreSQL JSON accepts numbers beyond even NUMERIC's precision.
|
|
{"id": "beyond-numeric", "data": '{"x": ' + "9" * 131073 + "}"},
|
|
{"id": "negative-zero", "data": '{"x": -0}'},
|
|
{"id": "float", "data": json.dumps({"x": float(expected)})},
|
|
{"id": "exponent", "data": '{"x": 42e0}'},
|
|
{"id": "string", "data": json.dumps({"x": str(expected)})},
|
|
{"id": "boolean", "data": '{"x": true}'},
|
|
{"id": "null", "data": '{"x": null}'},
|
|
{"id": "array", "data": '{"x": [42]}'},
|
|
{"id": "object", "data": '{"x": {}}'},
|
|
{"id": "missing", "data": "{}"},
|
|
]
|
|
# Insert raw JSON to retain -0 and exponent spellings on both backends.
|
|
await connection.execute(text("INSERT INTO json_integer_matching (id, data) VALUES (:id, :data)"), rows)
|
|
result = await connection.execute(select(table.c.id).where(json_match(table.c.data, "x", expected)))
|
|
expected_ids = {str(expected)} | ({"negative-zero"} if expected == 0 else set())
|
|
assert set(result.scalars()) == expected_ids
|