calcite自定义数据类型

Posted 境悟初

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了calcite自定义数据类型相关的知识,希望对你有一定的参考价值。

calcite本身基于JDBC规范实现了基础的数据类型,但不是所有类型。
比如空间类型Geometry,只是简单的存在。
当我们想要自定义数据类型时,可以从以下方面修改源码。

下面的修改经过实践测试。

扩展了Geometry的具体数据类型,增加了 TRAJECTORYROAD_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));

以上是关于calcite自定义数据类型的主要内容,如果未能解决你的问题,请参考以下文章

看这篇就够了丨基于Calcite框架的SQL语法扩展探索

Apache Calcite 功能简析及在 Flink 的应用

95-910-330-源码-FlinkSQL-Calcite-Flink结合Calcite

Apache Calcite 学习

Apache Calcite进行SQL解析

Flink SQL 之 Calcite Volcano优化器(源码解析)