Skip to content
Closed
5 changes: 5 additions & 0 deletions java/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
<groupId>com.aayushatharva.brotli4j</groupId>
<artifactId>brotli4j</artifactId>
</dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>${jts.version}</version>
</dependency>

<!-- test inter-project -->
<dependency>
Expand Down
27 changes: 27 additions & 0 deletions java/core/src/java/org/apache/orc/GeospatialColumnStatistics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.orc;

import org.apache.orc.geospatial.BoundingBox;
import org.apache.orc.geospatial.GeospatialTypes;

public interface GeospatialColumnStatistics extends ColumnStatistics {
BoundingBox getBoundingBox();
GeospatialTypes getGeospatialTypes();
}
41 changes: 41 additions & 0 deletions java/core/src/java/org/apache/orc/OrcUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package org.apache.orc;

import org.apache.orc.TypeDescription.EdgeInterpolationAlgorithm;
import org.apache.orc.impl.ParserUtils;
import org.apache.orc.impl.ReaderImpl;
import org.apache.orc.impl.SchemaEvolution;
Expand Down Expand Up @@ -171,6 +172,23 @@ private static void appendOrcTypes(List<OrcProto.Type> result, TypeDescription t
type.setPrecision(typeDescr.getPrecision());
type.setScale(typeDescr.getScale());
break;
case Geography:
type.setKind(OrcProto.Type.Kind.GEOGRAPHY);
type.setAlgorithm(switch (typeDescr.getEdgeInterpolationAlgorithm()) {
case SPHERICAL -> OrcProto.Type.EdgeInterpolationAlgorithm.SPHERICAL;
case VINCENTY -> OrcProto.Type.EdgeInterpolationAlgorithm.VINCENTY;
case THOMAS -> OrcProto.Type.EdgeInterpolationAlgorithm.THOMAS;
case ANDOYER -> OrcProto.Type.EdgeInterpolationAlgorithm.ANDOYER;
case KARNEY -> OrcProto.Type.EdgeInterpolationAlgorithm.KARNEY;
default -> throw new IllegalArgumentException("Unknown interpolation algorithm: " +
typeDescr.getEdgeInterpolationAlgorithm());
});
type.setCrs(typeDescr.getCrs());
break;
case Geometry:
type.setKind(OrcProto.Type.Kind.GEOMETRY);
type.setCrs(typeDescr.getCrs());
break;
case LIST:
type.setKind(OrcProto.Type.Kind.LIST);
type.addSubtypes(children.get(0).getId());
Expand Down Expand Up @@ -325,6 +343,29 @@ TypeDescription convertTypeFromProtobuf(List<OrcProto.Type> types,
result.withPrecision(type.getPrecision());
}
break;
case GEOMETRY:
result = TypeDescription.createGeometry();
if (type.hasCrs()) {
result.withCRS(type.getCrs());
}
break;
case GEOGRAPHY:
result = TypeDescription.createGeography();
if (type.hasCrs()) {
result.withCRS(type.getCrs());
}
result.withEdgeInterpolationAlgorithm(
switch (type.getAlgorithm()) {
case SPHERICAL -> EdgeInterpolationAlgorithm.SPHERICAL;
case VINCENTY -> EdgeInterpolationAlgorithm.VINCENTY;
case THOMAS -> EdgeInterpolationAlgorithm.THOMAS;
case ANDOYER -> EdgeInterpolationAlgorithm.ANDOYER;
case KARNEY -> EdgeInterpolationAlgorithm.KARNEY;
default -> throw new IllegalArgumentException("Unknown interpolation algorithm: " +
type.getAlgorithm());
}
);
break;
case LIST:
if (type.getSubtypesCount() != 1) {
throw new FileFormatException("LIST type should contain exactly " +
Expand Down
84 changes: 83 additions & 1 deletion java/core/src/java/org/apache/orc/TypeDescription.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,29 @@ public class TypeDescription
public static final long MAX_DECIMAL64 = 999_999_999_999_999_999L;
public static final long MIN_DECIMAL64 = -MAX_DECIMAL64;
private static final int DEFAULT_LENGTH = 256;
private static final String DEFAULT_CRS = "OGC:CRS84";
static final Pattern UNQUOTED_NAMES = Pattern.compile("^[a-zA-Z0-9_]+$");

// type attributes
public static final String ENCRYPT_ATTRIBUTE = "encrypt";
public static final String MASK_ATTRIBUTE = "mask";

public enum EdgeInterpolationAlgorithm {
SPHERICAL("spherical"),
VINCENTY("vincenty"),
THOMAS("thomas"),
ANDOYER("andoyer"),
KARNEY("karney");

EdgeInterpolationAlgorithm(String name) {
this.name = name;
}
final String name;
}

private static final EdgeInterpolationAlgorithm DEFAULT_EDGE_INTERPOLATION_ALGORITHM
= EdgeInterpolationAlgorithm.SPHERICAL;

@Override
public int compareTo(TypeDescription other) {
if (this == other) {
Expand Down Expand Up @@ -116,7 +133,9 @@ public enum Category {
MAP("map", false),
STRUCT("struct", false),
UNION("uniontype", false),
TIMESTAMP_INSTANT("timestamp with local time zone", true);
TIMESTAMP_INSTANT("timestamp with local time zone", true),
Geometry("geometry", true),
Geography("geography", true);

Category(String name, boolean isPrimitive) {
this.name = name;
Expand Down Expand Up @@ -187,6 +206,14 @@ public static TypeDescription createDecimal() {
return new TypeDescription(Category.DECIMAL);
}

public static TypeDescription createGeometry() {
return new TypeDescription(Category.Geometry);
}

public static TypeDescription createGeography() {
return new TypeDescription(Category.Geography);
}

/**
* Parse TypeDescription from the Hive type names. This is the inverse
* of TypeDescription.toString()
Expand Down Expand Up @@ -239,6 +266,26 @@ public TypeDescription withScale(int scale) {
return this;
}

public TypeDescription withCRS(String crs) {
if (category != Category.Geometry &&
category != Category.Geography) {
throw new IllegalArgumentException("crs is only allowed on Geometry/Geography" +
" and not " + category.name);
}
this.crs = crs;
return this;
}

public TypeDescription withEdgeInterpolationAlgorithm(
EdgeInterpolationAlgorithm edgeInterpolationAlgorithm) {
if (category != Category.Geography) {
throw new IllegalArgumentException("edgeInterpolationAlgorithm is only allowed on Geography" +
" and not " + category.name);
}
this.edgeInterpolationAlgorithm = edgeInterpolationAlgorithm;
return this;
}

/**
* Set an attribute on this type.
* @param key the attribute name
Expand Down Expand Up @@ -366,6 +413,8 @@ public TypeDescription clone() {
result.maxLength = maxLength;
result.precision = precision;
result.scale = scale;
result.crs = crs;
result.edgeInterpolationAlgorithm = edgeInterpolationAlgorithm;
if (fieldNames != null) {
result.fieldNames.addAll(fieldNames);
}
Expand Down Expand Up @@ -557,6 +606,14 @@ public int getScale() {
return scale;
}

public String getCrs() {
return crs;
}

public EdgeInterpolationAlgorithm getEdgeInterpolationAlgorithm() {
return edgeInterpolationAlgorithm;
}

/**
* For struct types, get the list of field names.
* @return the list of field names.
Expand Down Expand Up @@ -664,6 +721,9 @@ public TypeDescription(Category category) {
private int maxLength = DEFAULT_LENGTH;
private int precision = DEFAULT_PRECISION;
private int scale = DEFAULT_SCALE;
private String crs = DEFAULT_CRS;
private EdgeInterpolationAlgorithm edgeInterpolationAlgorithm
= DEFAULT_EDGE_INTERPOLATION_ALGORITHM;

static void printFieldName(StringBuilder buffer, String name) {
if (UNQUOTED_NAMES.matcher(name).matches()) {
Expand Down Expand Up @@ -691,6 +751,18 @@ public void printToBuffer(StringBuilder buffer) {
buffer.append(maxLength);
buffer.append(')');
break;
case Geometry:
buffer.append('(');
buffer.append(crs);
buffer.append(')');
break;
case Geography:
buffer.append('(');
buffer.append(crs);
buffer.append(',');
buffer.append(edgeInterpolationAlgorithm.name());
buffer.append(')');
break;
case LIST:
case MAP:
case UNION:
Expand Down Expand Up @@ -751,6 +823,16 @@ private void printJsonToBuffer(String prefix, StringBuilder buffer,
buffer.append(", \"length\": ");
buffer.append(maxLength);
break;
case Geometry:
buffer.append(", \"crs\": ");
buffer.append(crs);
break;
case Geography:
buffer.append(", \"crs\": ");
buffer.append(crs);
buffer.append(", \"edge_interpolation_algorithm\": ");
buffer.append(edgeInterpolationAlgorithm.name());
break;
case LIST:
case MAP:
case UNION:
Expand Down
Loading
Loading