prestodb/presto · error · ParsingException

Unexpected decimal literal: ${text}

Error message

Unexpected decimal literal: ${text}

What it means

AstBuilder.visitDecimalLiteral throws ParsingException when parsingOptions.getDecimalLiteralTreatment() is REJECT and the input contains a decimal literal (e.g. 1.23). The parser is configured to refuse decimal literals rather than coerce them to DOUBLE or DECIMAL.

Source

Thrown at presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java:2541

        return new GenericLiteral(getLocation(context), type, value);
    }

    @Override
    public Node visitIntegerLiteral(SqlBaseParser.IntegerLiteralContext context)
    {
        return new LongLiteral(getLocation(context), context.getText());
    }

    @Override
    public Node visitDecimalLiteral(SqlBaseParser.DecimalLiteralContext context)
    {
        switch (parsingOptions.getDecimalLiteralTreatment()) {
            case AS_DOUBLE:
                return new DoubleLiteral(getLocation(context), context.getText());
            case AS_DECIMAL:
                return new DecimalLiteral(getLocation(context), context.getText());
            case REJECT:
                throw new ParsingException("Unexpected decimal literal: " + context.getText());
        }
        throw new AssertionError("Unreachable");
    }

    @Override
    public Node visitDoubleLiteral(SqlBaseParser.DoubleLiteralContext context)
    {
        return new DoubleLiteral(getLocation(context), context.getText());
    }

    @Override
    public Node visitBooleanValue(SqlBaseParser.BooleanValueContext context)
    {
        return new BooleanLiteral(getLocation(context), context.getText());
    }

    @Override
    public Node visitInterval(SqlBaseParser.IntervalContext context)

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Change ParsingOptions to AS_DECIMAL so decimals become DecimalLiteral.
  2. Or use AS_DOUBLE if legacy DoubleLiteral semantics are desired.
  3. Rewrite the SQL to avoid decimal literals (e.g. CAST('1.23' AS DECIMAL)).
  4. If the server sets REJECT, remove or reconfigure that option at the caller site.

Example fix

// before
new SqlParser().createStatement("SELECT 1.5", ParsingOptions.builder().decimalLiteralTreatment(DecimalLiteralTreatment.REJECT).build());
// after
new SqlParser().createStatement("SELECT 1.5", ParsingOptions.builder().decimalLiteralTreatment(DecimalLiteralTreatment.AS_DECIMAL).build());
Defensive patterns

Strategy: validation

Validate before calling

// reject REJECT mode when SQL contains decimal literals
if (parsingOptions.getDecimalLiteralTreatment() == DecimalLiteralTreatment.REJECT
        && Pattern.compile("\\b\\d+\\.\\d+\\b").matcher(sql).find()) {
    throw new IllegalArgumentException("Decimal literal present but treatment is REJECT");
}

Type guard

boolean isDecimalLiteralRejected(ParsingOptions opts, String sql) {
    return opts.getDecimalLiteralTreatment() == DecimalLiteralTreatment.REJECT
        && Pattern.compile("\\d+\\.\\d+").matcher(sql).find();
}

Try / catch

try {
    parser.createStatement(sql, parsingOptions);
} catch (ParsingException e) {
    if (e.getMessage().startsWith("Unexpected decimal literal")) {
        ParsingOptions relaxed = ParsingOptions.builder(parsingOptions)
            .decimalLiteralTreatment(DecimalLiteralTreatment.AS_DECIMAL).build();
        parser.createStatement(sql, relaxed);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling SqlParser with ParsingOptions decimalLiteralTreatment=REJECT and parsing any statement containing a decimal number literal.

Common situations: Server/tooling code that explicitly sets REJECT to force legacy behavior, or API users who copied ParsingOptions.builder().decimalLiteralTreatment(DecimalLiteralTreatment.REJECT) from strict-mode examples.

Related errors


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