Search in sources :

Example 1 with RelDataTypeFamily

use of org.apache.calcite.rel.type.RelDataTypeFamily in project calcite by apache.

the class StandardConvertletTable method consistentType.

private static RelDataType consistentType(SqlRexContext cx, SqlOperandTypeChecker.Consistency consistency, List<RelDataType> types) {
    switch(consistency) {
        case COMPARE:
            final Set<RelDataTypeFamily> families = Sets.newHashSet(RexUtil.families(types));
            if (families.size() < 2) {
                // All arguments are of same family. No need for explicit casts.
                return null;
            }
            final List<RelDataType> nonCharacterTypes = Lists.newArrayList();
            for (RelDataType type : types) {
                if (type.getFamily() != SqlTypeFamily.CHARACTER) {
                    nonCharacterTypes.add(type);
                }
            }
            if (!nonCharacterTypes.isEmpty()) {
                final int typeCount = types.size();
                types = nonCharacterTypes;
                if (nonCharacterTypes.size() < typeCount) {
                    final RelDataTypeFamily family = nonCharacterTypes.get(0).getFamily();
                    if (family instanceof SqlTypeFamily) {
                        // argument. Give ourselves some headroom.
                        switch((SqlTypeFamily) family) {
                            case INTEGER:
                            case NUMERIC:
                                nonCharacterTypes.add(cx.getTypeFactory().createSqlType(SqlTypeName.BIGINT));
                        }
                    }
                }
            }
        // fall through
        case LEAST_RESTRICTIVE:
            return cx.getTypeFactory().leastRestrictive(types);
        default:
            return null;
    }
}
Also used : SqlTypeFamily(org.apache.calcite.sql.type.SqlTypeFamily) RelDataTypeFamily(org.apache.calcite.rel.type.RelDataTypeFamily) RelDataType(org.apache.calcite.rel.type.RelDataType)

Example 2 with RelDataTypeFamily

use of org.apache.calcite.rel.type.RelDataTypeFamily in project calcite by apache.

the class SqlTypeUtil method isComparable.

/**
 * Returns whether two types are comparable. They need to be scalar types of
 * the same family, or struct types whose fields are pairwise comparable.
 *
 * @param type1 First type
 * @param type2 Second type
 * @return Whether types are comparable
 */
public static boolean isComparable(RelDataType type1, RelDataType type2) {
    if (type1.isStruct() != type2.isStruct()) {
        return false;
    }
    if (type1.isStruct()) {
        int n = type1.getFieldCount();
        if (n != type2.getFieldCount()) {
            return false;
        }
        for (Pair<RelDataTypeField, RelDataTypeField> pair : Pair.zip(type1.getFieldList(), type2.getFieldList())) {
            if (!isComparable(pair.left.getType(), pair.right.getType())) {
                return false;
            }
        }
        return true;
    }
    RelDataTypeFamily family1 = null;
    RelDataTypeFamily family2 = null;
    // the Saffron type system happy.
    if (type1.getSqlTypeName() != null) {
        family1 = type1.getSqlTypeName().getFamily();
    }
    if (type2.getSqlTypeName() != null) {
        family2 = type2.getSqlTypeName().getFamily();
    }
    if (family1 == null) {
        family1 = type1.getFamily();
    }
    if (family2 == null) {
        family2 = type2.getFamily();
    }
    if (family1 == family2) {
        return true;
    }
    // If one of the arguments is of type 'ANY', return true.
    if (family1 == SqlTypeFamily.ANY || family2 == SqlTypeFamily.ANY) {
        return true;
    }
    // If one of the arguments is of type 'NULL', return true.
    if (family1 == SqlTypeFamily.NULL || family2 == SqlTypeFamily.NULL) {
        return true;
    }
    // We can implicitly convert from character to date
    if (family1 == SqlTypeFamily.CHARACTER && canConvertStringInCompare(family2) || family2 == SqlTypeFamily.CHARACTER && canConvertStringInCompare(family1)) {
        return true;
    }
    return false;
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelDataTypeFamily(org.apache.calcite.rel.type.RelDataTypeFamily)

Example 3 with RelDataTypeFamily

use of org.apache.calcite.rel.type.RelDataTypeFamily in project calcite by apache.

the class SqlTypeFactoryImpl method leastRestrictiveSqlType.

private RelDataType leastRestrictiveSqlType(List<RelDataType> types) {
    RelDataType resultType = null;
    int nullCount = 0;
    int nullableCount = 0;
    int javaCount = 0;
    int anyCount = 0;
    for (RelDataType type : types) {
        final SqlTypeName typeName = type.getSqlTypeName();
        if (typeName == null) {
            return null;
        }
        if (typeName == SqlTypeName.ANY) {
            anyCount++;
        }
        if (type.isNullable()) {
            ++nullableCount;
        }
        if (typeName == SqlTypeName.NULL) {
            ++nullCount;
        }
        if (isJavaType(type)) {
            ++javaCount;
        }
    }
    // if any of the inputs are ANY, the output is ANY
    if (anyCount > 0) {
        return createTypeWithNullability(createSqlType(SqlTypeName.ANY), nullCount > 0 || nullableCount > 0);
    }
    for (int i = 0; i < types.size(); ++i) {
        RelDataType type = types.get(i);
        RelDataTypeFamily family = type.getFamily();
        final SqlTypeName typeName = type.getSqlTypeName();
        if (typeName == SqlTypeName.NULL) {
            continue;
        }
        // Except if all types are either NULL or Java types.
        if (isJavaType(type) && javaCount + nullCount < types.size()) {
            final RelDataType originalType = type;
            type = typeName.allowsPrecScale(true, true) ? createSqlType(typeName, type.getPrecision(), type.getScale()) : typeName.allowsPrecScale(true, false) ? createSqlType(typeName, type.getPrecision()) : createSqlType(typeName);
            type = createTypeWithNullability(type, originalType.isNullable());
        }
        if (resultType == null) {
            resultType = type;
            if (resultType.getSqlTypeName() == SqlTypeName.ROW) {
                return leastRestrictiveStructuredType(types);
            }
        }
        RelDataTypeFamily resultFamily = resultType.getFamily();
        SqlTypeName resultTypeName = resultType.getSqlTypeName();
        if (resultFamily != family) {
            return null;
        }
        if (SqlTypeUtil.inCharOrBinaryFamilies(type)) {
            Charset charset1 = type.getCharset();
            Charset charset2 = resultType.getCharset();
            SqlCollation collation1 = type.getCollation();
            SqlCollation collation2 = resultType.getCollation();
            // TODO:  refine collation combination rules
            final int precision = SqlTypeUtil.maxPrecision(resultType.getPrecision(), type.getPrecision());
            // width.  Otherwise, result is fixed width.
            if (SqlTypeUtil.isLob(resultType)) {
                resultType = createSqlType(resultType.getSqlTypeName());
            } else if (SqlTypeUtil.isLob(type)) {
                resultType = createSqlType(type.getSqlTypeName());
            } else if (SqlTypeUtil.isBoundedVariableWidth(resultType)) {
                resultType = createSqlType(resultType.getSqlTypeName(), precision);
            } else {
                // this catch-all case covers type variable, and both fixed
                SqlTypeName newTypeName = type.getSqlTypeName();
                if (shouldRaggedFixedLengthValueUnionBeVariable()) {
                    if (resultType.getPrecision() != type.getPrecision()) {
                        if (newTypeName == SqlTypeName.CHAR) {
                            newTypeName = SqlTypeName.VARCHAR;
                        } else if (newTypeName == SqlTypeName.BINARY) {
                            newTypeName = SqlTypeName.VARBINARY;
                        }
                    }
                }
                resultType = createSqlType(newTypeName, precision);
            }
            Charset charset = null;
            SqlCollation collation = null;
            if ((charset1 != null) || (charset2 != null)) {
                if (charset1 == null) {
                    charset = charset2;
                    collation = collation2;
                } else if (charset2 == null) {
                    charset = charset1;
                    collation = collation1;
                } else if (charset1.equals(charset2)) {
                    charset = charset1;
                    collation = collation1;
                } else if (charset1.contains(charset2)) {
                    charset = charset1;
                    collation = collation1;
                } else {
                    charset = charset2;
                    collation = collation2;
                }
            }
            if (charset != null) {
                resultType = createTypeWithCharsetAndCollation(resultType, charset, collation);
            }
        } else if (SqlTypeUtil.isExactNumeric(type)) {
            if (SqlTypeUtil.isExactNumeric(resultType)) {
                // interval + datetime = datetime
                if (types.size() > (i + 1)) {
                    RelDataType type1 = types.get(i + 1);
                    if (SqlTypeUtil.isDatetime(type1)) {
                        resultType = type1;
                        return createTypeWithNullability(resultType, nullCount > 0 || nullableCount > 0);
                    }
                }
                if (!type.equals(resultType)) {
                    if (!typeName.allowsPrec() && !resultTypeName.allowsPrec()) {
                        // use the bigger primitive
                        if (type.getPrecision() > resultType.getPrecision()) {
                            resultType = type;
                        }
                    } else {
                        // Let the result type have precision (p), scale (s)
                        // and number of whole digits (d) as follows: d =
                        // max(p1 - s1, p2 - s2) s <= max(s1, s2) p = s + d
                        int p1 = resultType.getPrecision();
                        int p2 = type.getPrecision();
                        int s1 = resultType.getScale();
                        int s2 = type.getScale();
                        final int maxPrecision = typeSystem.getMaxNumericPrecision();
                        final int maxScale = typeSystem.getMaxNumericScale();
                        int dout = Math.max(p1 - s1, p2 - s2);
                        dout = Math.min(dout, maxPrecision);
                        int scale = Math.max(s1, s2);
                        scale = Math.min(scale, maxPrecision - dout);
                        scale = Math.min(scale, maxScale);
                        int precision = dout + scale;
                        assert precision <= maxPrecision;
                        assert precision > 0 || (resultType.getSqlTypeName() == SqlTypeName.DECIMAL && precision == 0 && scale == 0);
                        resultType = createSqlType(SqlTypeName.DECIMAL, precision, scale);
                    }
                }
            } else if (SqlTypeUtil.isApproximateNumeric(resultType)) {
                // TODO:  only promote when required
                if (SqlTypeUtil.isDecimal(type)) {
                    // Only promote to double for decimal types
                    resultType = createDoublePrecisionType();
                }
            } else {
                return null;
            }
        } else if (SqlTypeUtil.isApproximateNumeric(type)) {
            if (SqlTypeUtil.isApproximateNumeric(resultType)) {
                if (type.getPrecision() > resultType.getPrecision()) {
                    resultType = type;
                }
            } else if (SqlTypeUtil.isExactNumeric(resultType)) {
                if (SqlTypeUtil.isDecimal(resultType)) {
                    resultType = createDoublePrecisionType();
                } else {
                    resultType = type;
                }
            } else {
                return null;
            }
        } else if (SqlTypeUtil.isInterval(type)) {
            // interval + datetime = datetime
            if (types.size() > (i + 1)) {
                RelDataType type1 = types.get(i + 1);
                if (SqlTypeUtil.isDatetime(type1)) {
                    resultType = type1;
                    return createTypeWithNullability(resultType, nullCount > 0 || nullableCount > 0);
                }
            }
            if (!type.equals(resultType)) {
                // TODO jvs 4-June-2005:  This shouldn't be necessary;
                // move logic into IntervalSqlType.combine
                Object type1 = resultType;
                resultType = ((IntervalSqlType) resultType).combine(this, (IntervalSqlType) type);
                resultType = ((IntervalSqlType) resultType).combine(this, (IntervalSqlType) type1);
            }
        } else if (SqlTypeUtil.isDatetime(type)) {
            // datetime +/- interval (or integer) = datetime
            if (types.size() > (i + 1)) {
                RelDataType type1 = types.get(i + 1);
                if (SqlTypeUtil.isInterval(type1) || SqlTypeUtil.isIntType(type1)) {
                    resultType = type;
                    return createTypeWithNullability(resultType, nullCount > 0 || nullableCount > 0);
                }
            }
        } else {
            // leastRestrictiveByCast handle it
            return null;
        }
    }
    if (resultType != null && nullableCount > 0) {
        resultType = createTypeWithNullability(resultType, true);
    }
    return resultType;
}
Also used : RelDataTypeFamily(org.apache.calcite.rel.type.RelDataTypeFamily) SqlCollation(org.apache.calcite.sql.SqlCollation) Charset(java.nio.charset.Charset) RelDataType(org.apache.calcite.rel.type.RelDataType)

Example 4 with RelDataTypeFamily

use of org.apache.calcite.rel.type.RelDataTypeFamily in project flink by apache.

the class SqlCastFunction method getMonotonicity.

@Override
public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
    final RelDataType castFromType = call.getOperandType(0);
    final RelDataTypeFamily castFromFamily = castFromType.getFamily();
    final Collator castFromCollator = castFromType.getCollation() == null ? null : castFromType.getCollation().getCollator();
    final RelDataType castToType = call.getOperandType(1);
    final RelDataTypeFamily castToFamily = castToType.getFamily();
    final Collator castToCollator = castToType.getCollation() == null ? null : castToType.getCollation().getCollator();
    if (!Objects.equals(castFromCollator, castToCollator)) {
        // Cast between types compared with different collators: not monotonic.
        return SqlMonotonicity.NOT_MONOTONIC;
    } else if (castFromFamily instanceof SqlTypeFamily && castToFamily instanceof SqlTypeFamily && nonMonotonicCasts.containsEntry(castFromFamily, castToFamily)) {
        return SqlMonotonicity.NOT_MONOTONIC;
    } else {
        return call.getOperandMonotonicity(0);
    }
}
Also used : SqlTypeFamily(org.apache.calcite.sql.type.SqlTypeFamily) RelDataTypeFamily(org.apache.calcite.rel.type.RelDataTypeFamily) RelDataType(org.apache.calcite.rel.type.RelDataType) Collator(java.text.Collator)

Example 5 with RelDataTypeFamily

use of org.apache.calcite.rel.type.RelDataTypeFamily in project calcite by apache.

the class SqlCastFunction method getMonotonicity.

@Override
public SqlMonotonicity getMonotonicity(SqlOperatorBinding call) {
    RelDataTypeFamily castFrom = call.getOperandType(0).getFamily();
    RelDataTypeFamily castTo = call.getOperandType(1).getFamily();
    if (castFrom instanceof SqlTypeFamily && castTo instanceof SqlTypeFamily && nonMonotonicCasts.containsEntry(castFrom, castTo)) {
        return SqlMonotonicity.NOT_MONOTONIC;
    } else {
        return call.getOperandMonotonicity(0);
    }
}
Also used : SqlTypeFamily(org.apache.calcite.sql.type.SqlTypeFamily) RelDataTypeFamily(org.apache.calcite.rel.type.RelDataTypeFamily)

Aggregations

RelDataTypeFamily (org.apache.calcite.rel.type.RelDataTypeFamily)5 RelDataType (org.apache.calcite.rel.type.RelDataType)3 SqlTypeFamily (org.apache.calcite.sql.type.SqlTypeFamily)3 Charset (java.nio.charset.Charset)1 Collator (java.text.Collator)1 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)1 SqlCollation (org.apache.calcite.sql.SqlCollation)1