Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0e9abf3
Add newline before dependency in trino-iceberg pom
chenjian2664 Mar 25, 2026
2e99d49
Fix code indent
findepi Mar 25, 2026
03634ac
Do not fail when HMS returns new stats types
findepi Mar 24, 2026
6c2b98e
Use Hive sentinel bucket count for unbucketed thrift tables
dain Mar 22, 2026
dea459e
Fix invalid WKT in test data for OGC compliance
dain Jan 5, 2026
5bad232
Add assertSpatialEquals helper and convert tests
dain Jan 5, 2026
8b4c11b
Convert basic geometry functions from ESRI to JTS
dain Jan 4, 2026
7bf2eb8
Convert geometry accessor functions from ESRI to JTS
dain Jan 4, 2026
fd049bb
Add JTS geometry methods to GeometryUtils
dain Jan 8, 2026
520a1ea
Convert EncodedPolylineFunctions from ESRI to JTS
dain Jan 8, 2026
6b46946
Convert BingTileFunctions from ESRI to JTS
dain Jan 8, 2026
c03031f
Convert aggregation functions from ESRI to JTS
dain Jan 8, 2026
5ad28cf
Convert ST_Union and remaining GeoFunctions from ESRI to JTS
dain Jan 8, 2026
f447aed
Remove unused ESRI methods from GeometryUtils
dain Jan 8, 2026
11ed743
Convert spatial join and envelope handling from ESRI to JTS
dain Jan 4, 2026
b6adee6
Replace custom geometry serialization with EWKB
dain Jan 10, 2026
2c921ef
Convert Hadoop geometry reader from ESRI to JTS
dain Jan 4, 2026
309da4a
Use qualified imports for JTS objects
dain Jan 10, 2026
0ace6d2
Use JTS Geometry as native stack type
dain Jan 5, 2026
4425574
Use StandardCharsets constants
wendigo Mar 25, 2026
f100039
Implement next/previous value for LongTimestampType
dain Mar 25, 2026
39fca46
Add Iceberg v3 timestamp_ns and timestamptz_ns types
dain Mar 25, 2026
a729f3b
Fix error in transactional Hive table when original file is not a bucket
gertjanal Mar 17, 2026
b7f0afe
Bump io.airlift:airbase from 364 to 365 in the airlift group
dependabot[bot] Mar 25, 2026
3d8a99b
Recommend json_query/json_extract alternatives in json_array_get docs
findepi Mar 25, 2026
5e1c686
Remove json_extract from json_array_get deprecation guidance
findepi Mar 25, 2026
61b49b2
Add Teradata connector
sc250072 Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions core/trino-main/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@
<artifactId>stream</artifactId>
</dependency>

<dependency>
<groupId>com.esri.geometry</groupId>
<artifactId>esri-geometry-api</artifactId>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
*/
package io.trino.operator;

import com.esri.core.geometry.ogc.OGCGeometry;
import com.esri.core.geometry.ogc.OGCPoint;
import io.airlift.slice.Slice;
import io.trino.Session;
import io.trino.geospatial.Rectangle;
Expand All @@ -29,6 +27,8 @@
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.index.strtree.STRtree;

import java.util.List;
Expand All @@ -40,7 +40,8 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Verify.verifyNotNull;
import static io.airlift.slice.SizeOf.instanceSize;
import static io.trino.geospatial.serde.GeometrySerde.deserialize;
import static io.trino.geospatial.GeometryUtils.estimateMemorySize;
import static io.trino.geospatial.serde.JtsGeometrySerde.deserialize;
import static io.trino.operator.SyntheticAddress.decodePosition;
import static io.trino.operator.SyntheticAddress.decodeSliceIndex;
import static io.trino.operator.join.JoinUtils.channelsToPages;
Expand All @@ -67,20 +68,20 @@ public static final class GeometryWithPosition
{
private static final int INSTANCE_SIZE = instanceSize(GeometryWithPosition.class);

private final OGCGeometry ogcGeometry;
private final Geometry geometry;
private final int partition;
private final int position;

public GeometryWithPosition(OGCGeometry ogcGeometry, int partition, int position)
public GeometryWithPosition(Geometry geometry, int partition, int position)
{
this.ogcGeometry = requireNonNull(ogcGeometry, "ogcGeometry is null");
this.geometry = requireNonNull(geometry, "geometry is null");
this.partition = partition;
this.position = position;
}

public OGCGeometry getGeometry()
public Geometry getGeometry()
{
return ogcGeometry;
return geometry;
}

public int getPartition()
Expand All @@ -95,7 +96,7 @@ public int getPosition()

public long getEstimatedMemorySizeInBytes()
{
return INSTANCE_SIZE + ogcGeometry.estimateMemorySize();
return INSTANCE_SIZE + estimateMemorySize(geometry);
}
}

Expand Down Expand Up @@ -124,12 +125,9 @@ public PagesRTreeIndex(
checkArgument(!(constantRadius.isPresent() && radiusChannel.isPresent()), "Radius channel and constant radius are mutually exclusive");
}

private static Envelope getEnvelope(OGCGeometry ogcGeometry)
private static Envelope getEnvelope(Geometry geometry)
{
com.esri.core.geometry.Envelope env = new com.esri.core.geometry.Envelope();
ogcGeometry.getEsriGeometry().queryEnvelope(env);

return new Envelope(env.getXMin(), env.getXMax(), env.getYMin(), env.getYMax());
return geometry.getEnvelopeInternal();
}

/**
Expand All @@ -153,21 +151,21 @@ public int[] findJoinPositions(int position, Page probe, int probeGeometryChanne
int probePartition = probePartitionChannel.isPresent() ? INTEGER.getInt(probe.getBlock(probePartitionChannel.getAsInt()), position) : -1;

Slice slice = probeGeometryBlock.getSlice(probePosition);
OGCGeometry probeGeometry = deserialize(slice);
Geometry probeGeometry = deserialize(slice);
verifyNotNull(probeGeometry);
if (probeGeometry.isEmpty()) {
return EMPTY_ADDRESSES;
}

boolean probeIsPoint = probeGeometry instanceof OGCPoint;
boolean probeIsPoint = probeGeometry instanceof Point;

IntArrayList matchingPositions = new IntArrayList();

Envelope envelope = getEnvelope(probeGeometry);
rtree.query(envelope, item -> {
GeometryWithPosition geometryWithPosition = (GeometryWithPosition) item;
OGCGeometry buildGeometry = geometryWithPosition.getGeometry();
if (partitions.isEmpty() || (probePartition == geometryWithPosition.getPartition() && (probeIsPoint || (buildGeometry instanceof OGCPoint) || testReferencePoint(envelope, buildGeometry, probePartition)))) {
Geometry buildGeometry = geometryWithPosition.getGeometry();
if (partitions.isEmpty() || (probePartition == geometryWithPosition.getPartition() && (probeIsPoint || (buildGeometry instanceof Point) || testReferencePoint(envelope, buildGeometry, probePartition)))) {
if (radiusChannel == -1 && constantRadius.isEmpty()) {
if (spatialRelationshipTest.apply(buildGeometry, probeGeometry, OptionalDouble.empty())) {
matchingPositions.add(geometryWithPosition.getPosition());
Expand All @@ -188,7 +186,7 @@ public int[] findJoinPositions(int position, Page probe, int probeGeometryChanne
return matchingPositions.toIntArray();
}

private boolean testReferencePoint(Envelope probeEnvelope, OGCGeometry buildGeometry, int partition)
private boolean testReferencePoint(Envelope probeEnvelope, Geometry buildGeometry, int partition)
{
Envelope buildEnvelope = getEnvelope(buildGeometry);
Envelope intersection = buildEnvelope.intersection(probeEnvelope);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
*/
package io.trino.operator;

import com.esri.core.geometry.Geometry;
import com.esri.core.geometry.GeometryCursor;
import com.esri.core.geometry.Operator;
import com.esri.core.geometry.OperatorFactoryLocal;
import com.esri.core.geometry.ogc.OGCGeometry;
import io.airlift.slice.Slice;
import io.airlift.units.DataSize;
import io.trino.Session;
Expand All @@ -30,6 +25,7 @@
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.index.strtree.AbstractNode;
import org.locationtech.jts.index.strtree.ItemBoundable;
import org.locationtech.jts.index.strtree.STRtree;
Expand All @@ -43,7 +39,7 @@

import static com.google.common.base.Verify.verifyNotNull;
import static io.airlift.slice.SizeOf.instanceSize;
import static io.trino.geospatial.serde.GeometrySerde.deserialize;
import static io.trino.geospatial.serde.JtsGeometrySerde.deserialize;
import static io.trino.operator.PagesSpatialIndex.EMPTY_INDEX;
import static io.trino.operator.SyntheticAddress.decodePosition;
import static io.trino.operator.SyntheticAddress.decodeSliceIndex;
Expand Down Expand Up @@ -101,7 +97,6 @@ public PagesSpatialIndexSupplier(
private static STRtree buildRTree(LongArrayList addresses, List<ObjectArrayList<Block>> channels, int geometryChannel, OptionalInt radiusChannel, OptionalDouble constantRadius, OptionalInt partitionChannel)
{
STRtree rtree = new STRtree();
Operator relateOperator = OperatorFactoryLocal.getInstance().getOperator(Operator.Type.Relate);

for (int position = 0; position < addresses.size(); position++) {
long pageAddress = addresses.getLong(position);
Expand All @@ -117,9 +112,9 @@ private static STRtree buildRTree(LongArrayList addresses, List<ObjectArrayList<
}

Slice slice = block.getSlice(valueBlockPosition);
OGCGeometry ogcGeometry = deserialize(slice);
verifyNotNull(ogcGeometry);
if (ogcGeometry.isEmpty()) {
Geometry geometry = deserialize(slice);
verifyNotNull(geometry);
if (geometry.isEmpty()) {
continue;
}

Expand All @@ -135,30 +130,30 @@ else if (radiusChannel.isPresent()) {
continue;
}

if (radiusChannel.isEmpty() && constantRadius.isEmpty()) {
// If radius is supplied, this is a distance query, for which our acceleration won't help.
accelerateGeometry(ogcGeometry, relateOperator);
}

int partition = -1;
if (partitionChannel.isPresent()) {
Block partitionBlock = channels.get(partitionChannel.getAsInt()).get(blockIndex);
partition = INTEGER.getInt(partitionBlock, blockPosition);
}

rtree.insert(getEnvelope(ogcGeometry, radius), new GeometryWithPosition(ogcGeometry, partition, position));
rtree.insert(getEnvelope(geometry, radius), new GeometryWithPosition(geometry, partition, position));
}

rtree.build();
return rtree;
}

private static Envelope getEnvelope(OGCGeometry ogcGeometry, double radius)
private static Envelope getEnvelope(Geometry geometry, double radius)
{
com.esri.core.geometry.Envelope envelope = new com.esri.core.geometry.Envelope();
ogcGeometry.getEsriGeometry().queryEnvelope(envelope);

return new Envelope(envelope.getXMin() - radius, envelope.getXMax() + radius, envelope.getYMin() - radius, envelope.getYMax() + radius);
Envelope envelope = geometry.getEnvelopeInternal();
if (radius == 0.0) {
return envelope;
}
return new Envelope(
envelope.getMinX() - radius,
envelope.getMaxX() + radius,
envelope.getMinY() - radius,
envelope.getMaxY() + radius);
}

private long computeMemorySizeInBytes(AbstractNode root)
Expand All @@ -174,19 +169,6 @@ private long computeMemorySizeInBytes(ItemBoundable item)
return ENVELOPE_INSTANCE_SIZE + ((GeometryWithPosition) item.getItem()).getEstimatedMemorySizeInBytes();
}

private static void accelerateGeometry(OGCGeometry ogcGeometry, Operator relateOperator)
{
// Recurse into GeometryCollections
GeometryCursor cursor = ogcGeometry.getEsriGeometryCursor();
while (true) {
Geometry esriGeometry = cursor.next();
if (esriGeometry == null) {
break;
}
relateOperator.accelerateGeometry(esriGeometry, null, Geometry.GeometryAccelerationDegree.enumMild);
}
}

// doesn't include memory used by channels and addresses which are shared with PagesIndex
public DataSize getEstimatedSize()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
*/
package io.trino.operator;

import com.esri.core.geometry.ogc.OGCGeometry;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListenableFuture;
import io.airlift.slice.Slice;
Expand All @@ -24,6 +23,7 @@
import io.trino.spi.type.Type;
import io.trino.sql.gen.JoinFilterFunctionCompiler.JoinFilterFunctionFactory;
import io.trino.sql.planner.plan.PlanNodeId;
import org.locationtech.jts.geom.Geometry;

import java.util.HashMap;
import java.util.List;
Expand All @@ -42,7 +42,7 @@ public class SpatialIndexBuilderOperator
@FunctionalInterface
public interface SpatialPredicate
{
boolean apply(OGCGeometry probe, OGCGeometry build, OptionalDouble radius);
boolean apply(Geometry probe, Geometry build, OptionalDouble radius);
}

public static final class SpatialIndexBuilderOperatorFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;

import static io.trino.json.JsonInputErrorNode.JSON_ERROR;
import static io.trino.spi.StandardErrorCode.GENERIC_INTERNAL_ERROR;
import static java.nio.charset.StandardCharsets.UTF_16LE;
import static java.nio.charset.StandardCharsets.UTF_32LE;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
Expand Down Expand Up @@ -57,7 +57,6 @@ public final class JsonInputFunctions
public static final String VARBINARY_UTF32_TO_JSON = "$varbinary_utf32_to_json";

private static final JsonMapper MAPPER = new JsonMapper();
private static final Charset UTF_32LE = Charset.forName("UTF-32LE");

private JsonInputFunctions() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ public final class JsonOutputFunctions
Slices.copiedBuffer(new ObjectNode(JsonNodeFactory.instance).asText(), StandardCharsets.UTF_16LE));
private static final EncodingSpecificConstants UTF_32 = new EncodingSpecificConstants(
JsonEncoding.UTF32_LE,
Charset.forName("UTF-32LE"),
Slices.copiedBuffer(new ArrayNode(JsonNodeFactory.instance).asText(), Charset.forName("UTF-32LE")),
Slices.copiedBuffer(new ObjectNode(JsonNodeFactory.instance).asText(), Charset.forName("UTF-32LE")));
StandardCharsets.UTF_32LE,
Slices.copiedBuffer(new ArrayNode(JsonNodeFactory.instance).asText(), StandardCharsets.UTF_32LE),
Slices.copiedBuffer(new ObjectNode(JsonNodeFactory.instance).asText(), StandardCharsets.UTF_32LE));

private JsonOutputFunctions() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.junit.jupiter.api.parallel.Execution;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import static com.google.common.io.BaseEncoding.base16;
import static io.trino.json.JsonInputErrorNode.JSON_ERROR;
Expand Down Expand Up @@ -164,13 +165,13 @@ public void testVarbinaryUtf16ToJson()
@Test
public void testVarbinaryUtf32ToJson()
{
assertThat(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(INPUT, Charset.forName("UTF-32LE")) + ", true)"))
assertThat(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(INPUT, StandardCharsets.UTF_32LE) + ", true)"))
.hasType(JSON_2016)
.isEqualTo(JSON_OBJECT);

// wrong input encoding

assertTrinoExceptionThrownBy(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(INPUT, Charset.forName("UTF-32BE")) + ", true)")::evaluate)
assertTrinoExceptionThrownBy(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(INPUT, StandardCharsets.UTF_32BE) + ", true)")::evaluate)
.hasErrorCode(JSON_INPUT_CONVERSION_ERROR)
.hasMessage("conversion to JSON failed: ");

Expand All @@ -186,12 +187,12 @@ public void testVarbinaryUtf32ToJson()
// correct encoding, incorrect input

// with unsuppressed input conversion error
assertTrinoExceptionThrownBy(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(ERROR_INPUT, Charset.forName("UTF-32LE")) + ", true)")::evaluate)
assertTrinoExceptionThrownBy(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(ERROR_INPUT, StandardCharsets.UTF_32LE) + ", true)")::evaluate)
.hasErrorCode(JSON_INPUT_CONVERSION_ERROR)
.hasMessage("conversion to JSON failed: ");

// with input conversion error suppressed and converted to JSON_ERROR
assertThat(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(ERROR_INPUT, Charset.forName("UTF-32LE")) + ", false)"))
assertThat(assertions.expression("\"$varbinary_utf32_to_json\"(" + toVarbinary(ERROR_INPUT, StandardCharsets.UTF_32LE) + ", false)"))
.hasType(JSON_2016)
.isEqualTo(JSON_ERROR);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.parallel.Execution;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import static io.trino.spi.type.VarcharType.VARCHAR;
import static java.nio.charset.StandardCharsets.UTF_16LE;
Expand Down Expand Up @@ -81,7 +81,7 @@ public void testJsonToVarbinaryUtf16()
public void testJsonToVarbinaryUtf32()
{
assertThat(assertions.expression("\"$json_to_varbinary_utf32\"(" + JSON_EXPRESSION + ", TINYINT '1', true)"))
.isEqualTo(new SqlVarbinary(OUTPUT.getBytes(Charset.forName("UTF-32LE"))));
.isEqualTo(new SqlVarbinary(OUTPUT.getBytes(StandardCharsets.UTF_32LE)));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.parallel.Execution;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import static com.google.common.io.BaseEncoding.base16;
import static io.trino.spi.StandardErrorCode.JSON_INPUT_CONVERSION_ERROR;
Expand Down Expand Up @@ -186,7 +186,7 @@ public void testOutputFormat()
"SELECT json_array(true RETURNING varbinary FORMAT JSON ENCODING UTF16)"))
.matches("VALUES " + varbinaryLiteral);

bytes = output.getBytes(Charset.forName("UTF_32LE"));
bytes = output.getBytes(StandardCharsets.UTF_32LE);
varbinaryLiteral = "X'" + base16().encode(bytes) + "'";
assertThat(assertions.query(
"SELECT json_array(true RETURNING varbinary FORMAT JSON ENCODING UTF32)"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.parallel.Execution;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import static com.google.common.io.BaseEncoding.base16;
import static io.trino.spi.StandardErrorCode.INVALID_PATH;
Expand Down Expand Up @@ -131,7 +131,7 @@ public void testInputFormat()
"SELECT json_exists(" + varbinaryLiteral + " FORMAT JSON ENCODING UTF16, 'lax $[1]')"))
.matches("VALUES true");

bytes = INPUT.getBytes(Charset.forName("UTF-32LE"));
bytes = INPUT.getBytes(StandardCharsets.UTF_32LE);
varbinaryLiteral = "X'" + base16().encode(bytes) + "'";

assertThat(assertions.query(
Expand Down
Loading
Loading