StaticextractExtracts the top-level ORDER BY clause from SQL, ignoring ORDER BY inside subqueries, block comments, line comments, single-quoted strings, and bracket/double-quoted identifiers.
Preserves the public static API for existing callers and tests.
StaticShouldDetermines whether the given params indicate paging should be applied.
StaticstripStrips a TOP N or TOP (N) clause from the beginning of a SELECT statement.
StaticWrapApplies a row cap to the outermost SELECT.
maxRows is treated as a hard ceiling: the result is guaranteed to
return at most maxRows rows whenever the SQL shape can be capped
without corrupting the query.
Strategy:
TOP N (SQL Server) or LIMIT N (PostgreSQL).TOP/LIMIT is present, reduce it to
min(existing, maxRows). The tighter cap wins.TOP PERCENT,
non-numeric TOP, UNION, WITH TIES, etc.), wrap with an
outer SELECT TOP N * FROM (…) AS _mj_capped (or LIMIT on PG).OFFSET 0 ROWS FETCH NEXT N ROWS ONLY via buildDataSQL.FOR JSON, FOR XML, OPTION (...), SELECT INTO,
mutations) are returned unchanged — the cap is moot
(FOR JSON/XML return one row) or the validator should have
rejected them earlier (mutations, SELECT INTO).Non-positive, non-finite, or fractional maxRows are sanitized
(<= 0 and non-finite are no-ops; fractional values are floored).
StaticWrapProduces paged DataSQL and CountSQL from resolved query SQL.
The fully-resolved SQL (after composition + Nunjucks)
0-based row offset
Maximum rows to return (page size)
Target database platform
DataSQL for paged results and CountSQL for total row count
Handles server-side pagination for query SQL by applying platform-specific paging clauses.
Data SQL — appends OFFSET/FETCH (SQL Server) or LIMIT/OFFSET (PostgreSQL) directly to the original SQL. The query is not wrapped in a CTE, so all column scopes, ORDER BY references, and table aliases remain valid. TOP is stripped on SQL Server since it conflicts with OFFSET.
Count SQL — wraps the original SQL (minus ORDER BY) in a CTE and produces
SELECT COUNT(*) AS TotalRowCount FROM [__count]. ORDER BY is irrelevant for counting and must be removed since SQL Server forbids it in CTEs without TOP.This approach eliminates the need for ORDER BY remapping (mapping column references from the inner query scope to the outer CTE scope), which was the primary source of paging bugs.