Skip to content

fix: inspect every table function in feature analysis and validation - #2760

Open
AndreasLanz01 wants to merge 2 commits into
JSQLParser:masterfrom
AndreasLanz01:fix/feature-rows-from-functions
Open

AndreasLanz01 wants to merge 2 commits into
JSQLParser:masterfrom
AndreasLanz01:fix/feature-rows-from-functions

Conversation

@AndreasLanz01

Copy link
Copy Markdown

What

Two visitors looked at only part of a TableFunction:

  1. StatementFeatureVisitor now checks every function of ROWS FROM (...) for purity. Before, it checked only TableFunction#getFunction(), which is null for ROWS FROM.
  2. SelectValidator now validates the functions of a table function, for f(...) and for every function of ROWS FROM (...). Before, it validated only Feature.tableFunction and PIVOT/UNPIVOT, so nothing in the arguments was validated.

Both use the existing TableFunction#getFunctions(), which returns the ROWS FROM list or the single function.

Why

StatementFeatureVisitor.analyse(statement, name -> false), i.e. no function is declared pure:

SQL Before After
SELECT * FROM pg_ls_dir('.') MODIFIES_DATA, MODIFIES_SCHEMA uncertain; pg_ls_dir unresolved unchanged
SELECT * FROM ROWS FROM (pg_ls_dir('.')) nothing uncertain, nothing unresolved same as the plain form

A read-only guard that uses mayModifyData() therefore accepted any function when it was wrapped in ROWS FROM.

SelectValidator with FeaturesAllowed.SELECT plus Feature.tableFunction: SELECT * FROM t WHERE a = f(?) reports jdbcParameter not allowed., but SELECT * FROM f(?) and SELECT * FROM ROWS FROM (f(1), g(?)) reported no error.

Testing

  • StatementFeatureVisitorTest: new nested class with 4 tests:

    • plain table function (regression control);
    • ROWS FROM with one function;
    • ROWS FROM with two functions; marking only the first one pure leaves the second one unresolved;
    • ROWS FROM ... WITH ORDINALITY AS r(n, name, ord).

    On base 26d3e02a the 3 ROWS FROM tests fail and the control passes.

  • SelectValidatorTest: a WHERE control and a parameterized test with 3 cases (f(?), ROWS FROM, ROWS FROM ... WITH ORDINALITY). On base 26d3e02a the 3 cases fail with Expected 1 errors, but got: [] and the control passes.

  • ./gradlew check on Windows 11 with the JDK 17 toolchain passes: 9,550 test cases, 0 failures, 0 errors, 25 skipped. Grammar ambiguity, Spotless, Checkstyle, PMD, SpotBugs and JaCoCo verification pass.

  • All SQL in the new tests executes on PostgreSQL 18.4 (? sent as $1 with PREPARE/EXECUTE; helper table t and functions f, g created first).

  • Not run: mvn verify, JMH (no grammar or parser change), Linux/macOS.

Also observed, but not changed

  • SelectValidator does not validate select items at all (call commented out with a @todo at SelectValidator.java:152-155). That is why the validator control uses WHERE.
  • FromItemVisitorAdapter.visit(TableFunction) is empty, so the generic adapter does not descend into table function arguments, for f(...) or ROWS FROM. Changing it would change behaviour for every adapter user.

Origin

First observed with com.manticore-projects.jsqlformatter:jsqlparser:5.4.104 and Dialect.POSTGRESQL. Reproduced on upstream master 26d3e02a78e061f5fecf2eb2e783bf0482e10840 with the default parser.

AI disclosure: this change was prepared with an AI coding agent (Claude Code) and reviewed by me.

StatementFeatureVisitor only checked TableFunction#getFunction(), which
is null for ROWS FROM (...), so every function listed there escaped the
purity check. Iterate TableFunction#getFunctions() instead.
SelectValidator only checked that table functions are allowed and never
validated the functions themselves, so features, names and nested
queries in their arguments went unchecked. This covers both f(..) and
every function of ROWS FROM (..).
@AndreasLanz01
AndreasLanz01 force-pushed the fix/feature-rows-from-functions branch from 74ca3db to a834064 Compare October 9, 2026 08:31

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant