calcite本身基于JDBC规范实现了基础的数据类型,但不是所有类型。
比如空间类型Geometry,只是简单的存在。
当我们想要自定义数据类型时,可以从以下方面修改源码。
下面的修改经过实践测试。
扩展了Geometry
的具体数据类型,增加了 TRAJECTORY
和ROAD_NETWORK
两种自定义类型。
org/apache/calcite/sql/type/SqlTypeFamily.java
GEOMETRY
TRAJECTORY,
ROAD_NETWORK,
getTypeNames
case GEOMETRY:
return ImmutableList.of(SqlTypeName.GEOMETRY, SqlTypeName.POINT,
SqlTypeName.MULTIPOINT, SqlTypeName.LINESTRING, SqlTypeName.MULTILINESTRING,
SqlTypeName.POLYGON, SqlTypeName.MULTIPOLYGON, SqlTypeName.GEOMETRYCOLLECTION);
case TRAJECTORY:
return ImmutableList.of(SqlTypeName.TRAJECTORY);
case ROAD_NETWORK:
return ImmutableList.of(SqlTypeName.ROADNETWORK);
getDefaultConcreteType
case GEOMETRY:
return factory.createSqlType(SqlTypeName.GEOMETRY);
// case GEOMETRYCOLLECTION:
// return factory.createSqlType(SqlTypeName.GEOMETRYCOLLECTION);
case TRAJECTORY:
return factory.createSqlType(SqlTypeName.TRAJECTORY);
case ROAD_NETWORK:
return factory.createSqlType(SqlTypeName.ROADNETWORK);
org/apache/calcite/sql/type/SqlTypeName.java
POINT(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.GEOMETRY),
MULTIPOINT(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.GEOMETRY),
LINESTRING(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.GEOMETRY),
MULTILINESTRING(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.GEOMETRY),
POLYGON(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.GEOMETRY),
MULTIPOLYGON(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.GEOMETRY),
GEOMETRYCOLLECTION(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.GEOMETRY),
GEOMETRY(PrecScale.NO_NO, false, ExtraSqlTypes.GEOMETRY, SqlTypeFamily.GEOMETRY),
TRAJECTORY(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.TRAJECTORY),
ROADNETWORK(PrecScale.NO_NO, false, Types.OTHER, SqlTypeFamily.ROAD_NETWORK),
org/apache/calcite/sql/type/SqlTypeUtil.java
canCastFrom
public static boolean canCastFrom(
RelDataType toType,
RelDataType fromType,
boolean coerce) {
if (toType.equals(fromType)) {
return true;
}
if (isAny(toType) || isAny(fromType)) {
return true;
}
final SqlTypeName fromTypeName = fromType.getSqlTypeName();
final SqlTypeName toTypeName = toType.getSqlTypeName();
// start
if (toTypeName.equals(fromTypeName)
|| (toType.getSqlTypeName() == SqlTypeName.GEOMETRY && fromTypeName.getFamily() == SqlTypeFamily.GEOMETRY)) {
return true;
}
// end
...
convertTypeToSpec
public static SqlDataTypeSpec convertTypeToSpec(RelDataType type,
String charSetName, int maxPrecision) {
SqlTypeName typeName = type.getSqlTypeName();
// TODO jvs 28-Dec-2004: support row types, user-defined types,
// interval types, multiset types, etc
assert typeName != null;
final SqlTypeNameSpec typeNameSpec;
// start 自定义类型
if (isAtomic(type) || isNull(type) || typeName == SqlTypeName.GEOMETRY) {
// end 自定义类型
...
org/apache/calcite/adapter/enumerable/RexToLixTranslator.java
translateLiteral
case POINT:
case MULTIPOINT:
case LINESTRING:
case MULTILINESTRING:
case POLYGON:
case MULTIPOLYGON:
case GEOMETRYCOLLECTION:
case GEOMETRY:
final Geometry geom = literal.getValueAs(Geometry.class);
final String wkt = geom.toString();
return Expressions.call(null, BuiltInMethod.ST_GEOM_FROM_TEXT.method,
Expressions.constant(wkt));
org/apache/calcite/avatica/ColumnMetaData.java
enum Rep
POINT(Point.class,100001),
MULTI_POINT(MultiPoint.class,100002),
LINESTRING(LineString.class,100003),
MULTI_LINESTRING(MultiLineString.class,100004),
POLYGON(Polygon.class,100005),
MULTI_POLYGON(MultiPolygon.class,100006),
TRAJECTORY(Trajectory.class,100007),
ROAD_NETWORK(RoadNetwork.class,100008),
GEOMETRY(Geometry.class,100009)
AvaticaType
public static class AvaticaType {
...
public String columnClassName() {
// edit start 因为java.sql.Types最好不要改,我们就直接修改这里吧
final Class<?> originCls = SqlType.valueOf(id).boxedClass();
final Class<?> deepCls = this.rep.clazz;
return originCls == Object.class || Geometry.class.isAssignableFrom(deepCls) ? deepCls.getName() : originCls.getName();
// return SqlType.valueOf(id).boxedClass().getName();
// edit end
}
org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
public Type getJavaClass(RelDataType type)
case POINT:
case MULTIPOINT:
case LINESTRING:
case MULTILINESTRING:
case POLYGON:
case MULTIPOLYGON:
case GEOMETRYCOLLECTION:
case GEOMETRY:
return Geometry.class;
case TRAJECTORY:
return Trajectory.class;
case ROADNETWORK:
return RoadNetwork.class;
org/apache/calcite/rex/RexBuilder.java
public RexNode makeLiteral(Object value, RelDataType type,
boolean allowCast, boolean trim)
case POINT:
case MULTIPOINT:
case LINESTRING:
case MULTILINESTRING:
case POLYGON:
case MULTIPOLYGON:
case GEOMETRYCOLLECTION:
case GEOMETRY:
return new RexLiteral((Comparable) value, guessType(value),
SqlTypeName.GEOMETRY);
org/apache/calcite/rex/RexLiteral.java
public static boolean valueMatchesType(
Comparable value,
SqlTypeName typeName,
boolean strict)
case POINT:
case MULTIPOINT:
case LINESTRING:
case MULTILINESTRING:
case POLYGON:
case MULTIPOLYGON:
case GEOMETRYCOLLECTION:
case GEOMETRY:
return value instanceof Geometry;
private static void appendAsJava(Comparable value, StringBuilder sb,
SqlTypeName typeName, RelDataType type, boolean java,
RexDigestIncludeType includeType)
case GEOMETRY:
final String wkt = value.toString();
sb.append(wkt);
break;
org/apache/calcite/sql/type/JavaToSqlTypeConversionRules.java
private final Map<Class<?>, SqlTypeName> rules
.put(Point.class, SqlTypeName.POINT)
.put(MultiPoint.class, SqlTypeName.MULTIPOINT)
.put(LineString.class, SqlTypeName.LINESTRING)
.put(MultiLineString.class, SqlTypeName.MULTILINESTRING)
.put(Polygon.class, SqlTypeName.POLYGON)
.put(MultiPolygon.class, SqlTypeName.MULTIPOLYGON)
.put(Geometry.class, SqlTypeName.GEOMETRY)
.put(GeometryCollection.class, SqlTypeName.GEOMETRYCOLLECTION)
.put(RoadNetwork.class, SqlTypeName.ROADNETWORK)
.put(Trajectory.class, SqlTypeName.TRAJECTORY)
org/apache/calcite/sql/type/SqlTypeAssignmentRule.java
static {
// GEOMETRY is assignable from ...
rules.add(SqlTypeName.ROADNETWORK, EnumSet.of(SqlTypeName.ROADNETWORK));
rules.add(SqlTypeName.TRAJECTORY, EnumSet.of(SqlTypeName.TRAJECTORY));
rules.add(SqlTypeName.GEOMETRY, EnumSet.of(SqlTypeName.GEOMETRY));
rules.add(SqlTypeName.POINT, EnumSet.of(SqlTypeName.GEOMETRY));
rules.add(SqlTypeName.MULTIPOINT, EnumSet.of(SqlTypeName.GEOMETRY));
rules.add(SqlTypeName.LINESTRING, EnumSet.of(SqlTypeName.GEOMETRY));
rules.add(SqlTypeName.MULTILINESTRING, EnumSet.of(SqlTypeName.GEOMETRY));
rules.add(SqlTypeName.POLYGON, EnumSet.of(SqlTypeName.GEOMETRY));
rules.add(SqlTypeName.MULTIPOLYGON, EnumSet.of(SqlTypeName.GEOMETRY));