prestodb/presto · error · SemanticException

EXPRESSION_NOT_CONSTANT

EXPRESSION_NOT_CONSTANT

Error message

Constant expression cannot contain column references

What it means

ConstantExpressionVerifier validates that expressions used where constants are required (e.g. parameter default values, EXPLAIN options) contain no column references. A DereferenceExpression (e.g. t.col) that itself appears in the expression's column-reference set is rejected with EXPRESSION_NOT_CONSTANT.

Source

Thrown at presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/ConstantExpressionVerifier.java:54

    }

    private static class ConstantExpressionVerifierVisitor
            extends DefaultTraversalVisitor<Void, Void>
    {
        private final Set<NodeRef<Expression>> columnReferences;
        private final Expression expression;

        public ConstantExpressionVerifierVisitor(Set<NodeRef<Expression>> columnReferences, Expression expression)
        {
            this.columnReferences = columnReferences;
            this.expression = expression;
        }

        @Override
        protected Void visitDereferenceExpression(DereferenceExpression node, Void context)
        {
            if (columnReferences.contains(NodeRef.<Expression>of(node))) {
                throw new SemanticException(EXPRESSION_NOT_CONSTANT, expression, "Constant expression cannot contain column references");
            }

            process(node.getBase(), context);
            return null;
        }

        @Override
        protected Void visitIdentifier(Identifier node, Void context)
        {
            throw new SemanticException(EXPRESSION_NOT_CONSTANT, expression, "Constant expression cannot contain column references");
        }

        @Override
        protected Void visitFieldReference(FieldReference node, Void context)
        {
            throw new SemanticException(EXPRESSION_NOT_CONSTANT, expression, "Constant expression cannot contain column references");
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Replace the column reference with a literal value or parameter placeholder (?)
  2. Wrap the value via a parameter (PREPARE/EXECUTE or session parameter) instead of referencing a column
  3. If row-dependent values are needed, move the expression into the query body rather than a constant context

Example fix

// before
-- constant context
SELECT * FROM t LIMIT :offset_col
// after
SELECT * FROM t LIMIT ?  -- bind a literal integer
Defensive patterns

Strategy: validation

Validate before calling

if (expression instanceof DereferenceExpression && ConstantExpressionVerifier.isColumnReference(expression, metadata)) {
    throw new IllegalArgumentException("Column reference not allowed in constant expression");
}

Type guard

boolean isLiteralOnly(Expression e) {
    return e instanceof Literal || e instanceof Parameter;
}

Try / catch

try {
    ConstantExpressionVerifier.verify(identity, expression, metadata, session);
} catch (SemanticException e) {
    if (e.getCode() == SemanticErrorCode.EXPRESSION_NOT_CONSTANT) { /* substitute literal or parameter */ }
    throw e;
}

Prevention

When it happens

Trigger: Passing a qualified column reference (a.b) as a constant expression — e.g. as a parameter value or generic-limitation-constant context — where the verifier's columnReferences set contains the dereference node.

Common situations: Using table-qualified column names in places expecting literals/parameters; generated SQL that substitutes identifiers instead of literals.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/17d30643c556084a. Report an issue: GitHub.