Support range and null queries in the API - #7154
Open
roed-math wants to merge 4 commits into
Open
Conversation
The API query parser now accepts the inclusive range syntax a..b under
the numeric type-prefixes i and f (either endpoint may be omitted), and
the unprefixed value None to match rows where a column is null (sNone
still gives the literal string "None"). Neither changes any working
query: i/f values containing ".." previously fell back to a junk
literal string, and bare None was compared as the string 'None', both
producing SQL type errors. Also fixes the cf prefix, which built
{"contains": ...} instead of {"$contains": ...} and so generated
invalid SQL. Documented on the API index page; verified with new tests
in lmfdb/api/test_api.py against devmirror (8 passed) plus html/yaml
spot-checks and pyflakes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review of #18 asked for regression coverage of the user-visible behavior the PR changes, so extract the type-prefix value decoding out of api_query into a pure helper parse_api_value and test it directly: - test_api_contains_float_query pins the cf fix ($contains, not contains) against nf_fields 6.0.177147.2, whose coeffs contain 0 but not 0.5. - test_parse_numeric plus an i11..11 endpoint query pin the ranges as inclusive; strict $gt/$lt returns nothing and fails both. - test_parse_api_value covers bare None vs sNone, the other prefixes, and the fallback of malformed typed values to their original strings. Route behavior is unchanged: meta keys starting with _ are still skipped, and a value whose conversion raises is still kept as a string (i.. still does not become an unconstrained query). Also document the s escape for range-looking values (si11..100) on the API index page, since such a value used to be searchable as a literal. Verified: sage -python -m pytest lmfdb/api/test_api.py -> 11 passed; sage -python -m pyflakes on both changed modules is clean; reverting the cf fix or replacing $gte/$lte with $gt/$lt fails the new tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The ls branch of the API query parser read qval[2] instead of qval[2:], so a list of strings was truncated to its first character: the example on the API index page, ec_curvedata?torsion_structure=ls2;2&_delim=;, searched for [2] and returned curves with torsion structure Z/2 rather than the intended Z/2 x Z/2. The other list prefixes (li, lf) already sliced correctly. Covered by a direct assertion in test_parse_api_value and by a new test_api_list_of_strings_query, which runs the documented example and checks the torsion structures that come back; both fail with the old qval[2]. Verified: sage -python -m pytest lmfdb/api/test_api.py -> 12 passed; pyflakes clean on both changed modules. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5066.
Closes #6693.
The API query parser now accepts an inclusive range syntax under the numeric type-prefixes:
conductor=i11..100translates to{"$gte": 11, "$lte": 100}, and either endpoint may be omitted (i389..,f..2.5). Ranges are only activated under thei/fprefixes, so bare ands-prefixed values containing..are untouched. The unprefixed valueNonenow matches rows where the column is null (e.g.gps_gl2zhat_fine?q_gonality=None, which used to produce a SQL type error).Two forms of value are reserved by this, and each keeps an escape. A value beginning with
iorfand containing..is now read as a numeric range, where before it fell through to the literal string (meaningful only on a text column); it remains searchable as a literal by prefixing it withs, as insi11..100. BareNoneis reserved for SQL null in the same way, withsNonefor the literal string "None". Both escapes are documented on the API index page next to the new syntax.Also fixes two pre-existing bugs in the same parser block:
cf(contains-float) built{"contains": ...}instead of{"$contains": ...}, and therefore generated invalid SQL;ls(list of strings) splitqval[2]instead ofqval[2:], truncating the list to its first character. This was visible in the API index page's own example:ec_curvedata?torsion_structure=ls2;2&_delim=;searched for[2], so it returned curves with torsion structure Z/2 instead of Z/2 x Z/2.The type-prefix decoding now lives in a pure helper
parse_api_value, solmfdb/api/test_api.pycan pin the parser contracts directly (inclusive endpoints, bareNonevssNone, thecfandlsregressions, malformed typed values falling back to strings) alongside end-to-end range, null, containment and list queries against real tables.Ported from roed-math#18, where the full write-up and comment history live.
🤖 Generated with Claude Code