hs-web/hsweb-framework · error · IllegalArgumentException
table function[" + tableFunction + "] must have alias
Error message
table function[" + tableFunction + "] must have alias
What it means
QueryAnalyzerImpl visits a JSqlParser TableFunction in the FROM clause and requires it to carry an alias, because the analyzer resolves every result column to an owner alias. A table function has no real table name, so without an alias there is no stable identifier to bind columns against, and the analyzer fails fast with IllegalArgumentException.
Solutions
- Add an alias to the table function in the SQL: `FROM generate_series(1,10) AS gs`.
- If the SQL is generated by your code, append the alias programmatically before calling the analyzer.
- If you do not actually need a table function, replace it with a plain table or a CTE (WITH ...) that is already aliased.
Example fix
// before String dql = "select * from generate_series(1,3)"; // after String dql = "select * from generate_series(1,3) as gs";
Defensive patterns
Strategy: validation
Validate before calling
if (sql.toLowerCase().matches(".*\\bfrom\\s+[a-z_0-9]+\\s*\\(.*") && !sql.toLowerCase().matches(".*\\bfrom\\s+[a-z_0-9]+\\s*\\([^)]*\\)\\s+(as\\s+)?[a-z_][a-z_0-9]*.*")) { throw new IllegalArgumentException("table function in FROM must have an alias"); } Prevention
- Always alias table functions: `... AS t`
- Add a unit test for each dynamic SQL template
- Lint SQL snippets for unaliased FROM items
When it happens
Trigger: Executing a dynamic query (e.g. via QueryHelper/dql) whose FROM clause contains a table function such as `generate_series(...)`, `unnest(...)`, or a custom table-valued function without `AS alias`, causing visit(TableFunction) to throw.
Common situations: Hand-written dynamic SQL snippets that work in a raw psql/MySQL console (where aliasing is optional) are fed into the hsweb query analyzer; users porting SQL from other frameworks forget the mandatory alias rule.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- table or view " + tableName.getName() + " not found in " +…
- table " + table.getName() + " not found in join
- table " + table + " not found in from or join
- column [" + column.getColumnName() + "] not found in " +…
- select can not be without 'from'
AI-assisted analysis of hs-web/hsweb-framework@b2cfc85a57 (2026-09-13).
Data as JSON: /api/errors/1b97baab7b3eb12c.
Report an issue: GitHub.
Appendix: source
Thrown at hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java:388
for (Alias.AliasColumn alias : valuesList.getAlias().getAliasColumns()) {
RDBColumnMetadata ignore = view.getColumn(parsePlainName(alias.name)).orElse(null);
}
}
view.setName(name);
view.setRealName(name);
view.setSchema(database.getMetadata().getCurrentSchema());
view.setAlias(name);
Table table = new Table(name, view);
select = new QueryAnalyzer.Select(new ArrayList<>(), table);
}
@Override
public void visit(TableFunction tableFunction) {
if (tableFunction.getAlias() == null) {
throw new IllegalArgumentException("table function[" + tableFunction + "] must have alias");
}
String name = parsePlainName(tableFunction.getAlias().getName());
FakeTable view = new FakeTable();
view.setName(name);
view.setSchema(database.getMetadata().getCurrentSchema());
view.setAlias(name);
Table table = new Table(name, view);
select = new QueryAnalyzer.Select(new ArrayList<>(), table);
}
@Override
public void visit(ParenthesisFromItem aThis) {
aThis.getFromItem().accept(this);View on GitHub (pinned to b2cfc85a57)