{"record":{"id":"8473f9ea87709d11","repo":"hs-web/hsweb-framework","slug":"select-can-not-be-without-from","errorCode":null,"errorMessage":"select can not be without 'from'","messagePattern":"select can not be without 'from'","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java","lineNumber":567,"sourceCode":"            }\n        }\n\n        if (metadata == null) {\n            throw new IllegalStateException(\"column [\" + column.getColumnName() + \"] not found in \" + table.metadata.getName());\n        }\n\n        select.columnList.add(new QueryAnalyzer.Column(metadata.getRealName(), aliasName, table.alias, metadata));\n\n\n    }\n\n    @Override\n    public void visit(PlainSelect select) {\n\n        FromItem from = select.getFromItem();\n\n        if (from == null) {\n            throw new IllegalArgumentException(\"select can not be without 'from'\");\n        }\n        from.accept(this);\n\n\n        List<net.sf.jsqlparser.statement.select.Join> joinList = select.getJoins();\n\n        if (joinList != null) {\n            for (net.sf.jsqlparser.statement.select.Join join : joinList) {\n                FromItem fromItem = join.getRightItem();\n                QueryAnalyzerImpl joinAn = new QueryAnalyzerImpl(database, (SelectBody) null, this);\n                fromItem.accept(joinAn);\n\n                Join.Type type;\n                if (join.isLeft()) {\n                    type = Join.Type.left;\n                } else if (join.isRight()) {\n                    type = Join.Type.right;\n                } else if (join.isInner()) {","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/hs-web/hsweb-framework/blob/b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/query/QueryAnalyzerImpl.java#L549-L585","documentation":"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.","triggerScenarios":"Executing a query like `select 1` or `select now()` (no FROM clause) through the dynamic query/DQL APIs that run QueryAnalyzerImpl.visit(PlainSelect).","commonSituations":"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.","solutions":["Add a FROM clause, e.g. `select 1 from dual` (or an equivalent single-row table).","Rewrite computed-only queries to use a dummy/CTE table: `with t as (select 1) select * from t`.","If you only need a scalar, bypass the query analyzer and use the native executor directly."],"exampleFix":"// before\n\"select now()\"\n// after\n\"select now() from dual\"","handlingStrategy":"validation","validationCode":"if (!dql.trim().toLowerCase().matches(\".*\\\\bfrom\\\\b.*\")) { throw new IllegalArgumentException(\"dynamic query requires a FROM clause\"); }","typeGuard":null,"tryCatchPattern":"try { analyzer.analyze(dql); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"without 'from'\")) { dql = dql.replaceFirst(\"(?i)select\", \"select ... from dual select\"); } throw e; }","preventionTips":["Never emit SELECT without FROM in dynamic query templates","Guard template branches that conditionally render FROM","Use a dummy single-row table for computed-only selects"],"tags":["sql","missing-from-clause","query-analyzer"],"backgroundTag":"missing-required-argument","analyzedSha":"b2cfc85a57c70bf5b5cf6e7edae2d37102652ec8","analyzedAt":"2026-09-13T09:05:02.172Z","contentChangedAt":"2026-09-13T09:05:02.172Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}