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;
}
}
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;
}
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;
}
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);
}
}
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);
}
}
Aggregations