{"record":{"id":"a833a070ab17a03c","repo":"apache/cassandra","slug":"only-column-names-and-monotonic-scalar-functions-a","errorCode":null,"errorMessage":"Only column names and monotonic scalar functions are supported in the GROUP BY clause.","messagePattern":"Only column names and monotonic scalar functions are supported in the GROUP BY clause\\.","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/selection/Selector.java","lineNumber":612,"sourceCode":"\n    /**\n     * A selector is terminal if it doesn't require any input for it's output to be computed, i.e. if {@link #getOutput}\n     * result doesn't depend of {@link #addInput}. This is typically the case of a constant value or functions on constant\n     * values.\n     */\n    public boolean isTerminal()\n    {\n        return false;\n    }\n\n    public void prepare(FunctionContext context) {}\n\n    /**\n     * Checks that this selector is valid for GROUP BY clause.\n     */\n    public void validateForGroupBy()\n    {\n        throw invalidRequest(\"Only column names and monotonic scalar functions are supported in the GROUP BY clause.\");\n    }\n\n    protected abstract int serializedSize(int version);\n\n    protected abstract void serialize(DataOutputPlus out, int version) throws IOException;\n\n    protected static void writeType(DataOutputPlus out, AbstractType<?> type) throws IOException\n    {\n        out.writeUTF(type.asCQL3Type().toString());\n    }\n\n    protected static int sizeOf(AbstractType<?> type)\n    {\n        return TypeSizes.sizeof(type.asCQL3Type().toString());\n    }\n}\n","sourceCodeStart":594,"sourceCodeEnd":629,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/selection/Selector.java#L594-L629","documentation":"This default implementation of Selector.validateForGroupBy rejects selectors that are not simple column names or supported monotonic scalar functions. GROUP BY in Cassandra requires each selected expression to be either a bare column or an allowed monotonic function of the grouped columns; anything else (aggregations, WRITETIME/TTL, arbitrary functions, non-monotonic expressions) fails validation at prepare time.","triggerScenarios":"`SELECT count(*) FROM t GROUP BY k;` — aggregate in selection with GROUP BY; `SELECT writetime(v) FROM t GROUP BY k;`; arbitrary scalar functions or expressions like a+b in the selection clause alongside GROUP BY.","commonSituations":"Porting SQL habits (GROUP BY with computed or aggregated select lists) to Cassandra; composing selectors from higher-level query builders that add functions automatically; upgrading code that relied on relaxed validation.","solutions":["Select only bare columns: `SELECT k, v FROM t GROUP BY k;` and compute functions/aggregations client-side.","If a function is needed, use one of the supported monotonic scalar functions of the grouped columns.","Remove aggregates (count, sum, etc.) from the select list when GROUP BY is present; use plain selection and aggregate over rows returned.","Restructure the query — e.g. use a separate aggregation query without GROUP BY or do grouping in the application."],"exampleFix":"// before\nSELECT count(*), k FROM t GROUP BY k;\n// after\nSELECT k, v FROM t GROUP BY k; -- aggregate client-side","handlingStrategy":"validation","validationCode":"for (Selector s : selectItems) if (!(s instanceof ColumnIdentifier) && !isAllowedMonotonicScalarFunction(s)) throw new IllegalArgumentException(\"GROUP BY supports only columns and monotonic scalar functions\");","typeGuard":null,"tryCatchPattern":"try { session.execute(selectWithGroupBy); } catch (InvalidRequestException e) { if (e.getMessage().contains(\"GROUP BY clause\")) { /* strip functions/aggregates from select list */ } else throw e; }","preventionTips":["Only select bare columns of the GROUP BY key set.","Do client-side aggregation instead of aggregate functions with GROUP BY.","Keep query builders from injecting writetime/ttl/functions into grouped selects."],"tags":["cql","group-by","selector","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}