hs-web/hsweb-framework · error · IllegalArgumentException

select can not be without 'from'

Error message

select can not be without 'from'

What it means

When visiting a PlainSelect, the analyzer requires a FROM item because every result column must be bound to an owning table. A SELECT without FROM cannot be resolved to any table metadata, so an IllegalArgumentException is thrown before analysis proceeds.

Solutions

  1. Add a FROM clause, e.g. `select 1 from dual` (or an equivalent single-row table).
  2. Rewrite computed-only queries to use a dummy/CTE table: `with t as (select 1) select * from t`.
  3. If you only need a scalar, bypass the query analyzer and use the native executor directly.

Example fix

// before
"select now()"
// after
"select now() from dual"
Defensive patterns

Strategy: validation

Validate before calling

if (!dql.trim().toLowerCase().matches(".*\\bfrom\\b.*")) { throw new IllegalArgumentException("dynamic query requires a FROM clause"); }

Try / catch

try { analyzer.analyze(dql); } catch (IllegalArgumentException e) { if (e.getMessage().contains("without 'from'")) { dql = dql.replaceFirst("(?i)select", "select ... from dual select"); } throw e; }

Prevention

When it happens

Trigger: Executing a query like `select 1` or `select now()` (no FROM clause) through the dynamic query/DQL APIs that run QueryAnalyzerImpl.visit(PlainSelect).

Common situations: Existence checks or computed-value queries written in scalar-SQL style; templates that emit the FROM clause conditionally and drop it when parameters are empty.

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


AI-assisted analysis of hs-web/hsweb-framework@b2cfc85a57 (2026-09-13). Data as JSON: /api/errors/8473f9ea87709d11. Report an issue: GitHub.

Appendix: source

Thrown at hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java:567

            }
        }

        if (metadata == null) {
            throw new IllegalStateException("column [" + column.getColumnName() + "] not found in " + table.metadata.getName());
        }

        select.columnList.add(new QueryAnalyzer.Column(metadata.getRealName(), aliasName, table.alias, metadata));


    }

    @Override
    public void visit(PlainSelect select) {

        FromItem from = select.getFromItem();

        if (from == null) {
            throw new IllegalArgumentException("select can not be without 'from'");
        }
        from.accept(this);


        List<net.sf.jsqlparser.statement.select.Join> joinList = select.getJoins();

        if (joinList != null) {
            for (net.sf.jsqlparser.statement.select.Join join : joinList) {
                FromItem fromItem = join.getRightItem();
                QueryAnalyzerImpl joinAn = new QueryAnalyzerImpl(database, (SelectBody) null, this);
                fromItem.accept(joinAn);

                Join.Type type;
                if (join.isLeft()) {
                    type = Join.Type.left;
                } else if (join.isRight()) {
                    type = Join.Type.right;
                } else if (join.isInner()) {

View on GitHub (pinned to b2cfc85a57)