All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.sql.impl.calcite.validate.literal.NumericLiteral Maven / Gradle / Ivy

/*
 * Copyright (c) 2008-2021, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.sql.impl.calcite.validate.literal;

import com.hazelcast.sql.impl.calcite.validate.types.HazelcastIntegerType;
import com.hazelcast.sql.impl.calcite.validate.types.HazelcastTypeFactory;
import com.hazelcast.sql.impl.type.converter.BigDecimalConverter;
import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.sql.SqlLiteral;
import com.hazelcast.org.apache.calcite.sql.SqlNumericLiteral;
import com.hazelcast.org.apache.calcite.sql.type.SqlTypeName;

import java.math.BigDecimal;

public final class NumericLiteral extends Literal {

    private final Mode mode;
    private final int bitWidth;

    private NumericLiteral(
        SqlLiteral original,
        Object value,
        SqlTypeName typeName,
        Mode mode,
        int bitWidth
    ) {
        super(original, value, typeName);

        this.mode = mode;
        this.bitWidth = bitWidth;
    }

    public static NumericLiteral create(SqlNumericLiteral original) {
        BigDecimal valueDecimal = (BigDecimal) original.getValue();

        if (original.isExact()) {
            if (original.getScale() == 0) {
                // Dealing with integer type family
                try {
                    long value = BigDecimalConverter.INSTANCE.asBigint(valueDecimal);

                    int bitWidth = HazelcastIntegerType.bitWidthOf(value);

                    RelDataType type = HazelcastIntegerType.create(bitWidth, false);

                    Object adjustedValue;

                    switch (type.getSqlTypeName()) {
                        case TINYINT:
                            adjustedValue = (byte) value;
                            break;

                        case SMALLINT:
                            adjustedValue = (short) value;
                            break;

                        case INTEGER:
                            adjustedValue = (int) value;
                            break;

                        default:
                            assert type.getSqlTypeName() == SqlTypeName.BIGINT;
                            adjustedValue = value;
                    }

                    return new NumericLiteral(
                        original,
                        adjustedValue,
                        type.getSqlTypeName(),
                        Mode.INTEGER,
                        bitWidth
                    );
                } catch (Exception ignore) {
                    // Fallback to DECIMAL
                }
            }

            // Dealing with DECIMAL
            return new NumericLiteral(
                original,
                valueDecimal,
                SqlTypeName.DECIMAL,
                Mode.FRACTIONAL_EXACT,
                0
            );

        } else {
            // Dealing with DOUBLE
            return new NumericLiteral(
                original,
                valueDecimal.doubleValue(),
                SqlTypeName.DOUBLE,
                Mode.FRACTIONAL_INEXACT,
                0
            );
        }
    }

    @Override
    public RelDataType getType(HazelcastTypeFactory typeFactory) {
        switch (mode) {
            case INTEGER:
                return HazelcastIntegerType.create(bitWidth, false);

            case FRACTIONAL_EXACT:
                return typeFactory.createSqlType(SqlTypeName.DECIMAL);

            default:
                assert mode == Mode.FRACTIONAL_INEXACT;

                return typeFactory.createSqlType(SqlTypeName.DOUBLE);
        }
    }

    private enum Mode {
        INTEGER,
        FRACTIONAL_EXACT,
        FRACTIONAL_INEXACT
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy