Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SEDONA-607] Return geometry with ST functions with exceptions #1525

Merged
merged 12 commits into from
Jul 23, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,21 @@ case class ST_GeomFromWKB(inputExpressions: Seq[Expression])
override def nullable: Boolean = true

override def eval(inputRow: InternalRow): Any = {
(inputExpressions.head.eval(inputRow)) match {
case (geomString: UTF8String) => {
// Parse UTF-8 encoded wkb string
Constructors.geomFromText(geomString.toString, FileDataSplitter.WKB).toGenericArrayData
}
case (wkb: Array[Byte]) => {
// convert raw wkb byte array to geometry
Constructors.geomFromWKB(wkb).toGenericArrayData
try {
(inputExpressions.head.eval(inputRow)) match {
case (geomString: UTF8String) => {
// Parse UTF-8 encoded wkb string
Constructors.geomFromText(geomString.toString, FileDataSplitter.WKB).toGenericArrayData
}
case (wkb: Array[Byte]) => {
// convert raw wkb byte array to geometry
Constructors.geomFromWKB(wkb).toGenericArrayData
}
case null => null
}
case null => null
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(inputRow, inputExpressions, e)
}
}

Expand All @@ -196,16 +201,21 @@ case class ST_GeomFromEWKB(inputExpressions: Seq[Expression])
override def nullable: Boolean = true

override def eval(inputRow: InternalRow): Any = {
(inputExpressions.head.eval(inputRow)) match {
case (geomString: UTF8String) => {
// Parse UTF-8 encoded wkb string
Constructors.geomFromText(geomString.toString, FileDataSplitter.WKB).toGenericArrayData
}
case (wkb: Array[Byte]) => {
// convert raw wkb byte array to geometry
Constructors.geomFromWKB(wkb).toGenericArrayData
try {
(inputExpressions.head.eval(inputRow)) match {
case (geomString: UTF8String) => {
// Parse UTF-8 encoded wkb string
Constructors.geomFromText(geomString.toString, FileDataSplitter.WKB).toGenericArrayData
}
case (wkb: Array[Byte]) => {
// convert raw wkb byte array to geometry
Constructors.geomFromWKB(wkb).toGenericArrayData
}
case null => null
}
case null => null
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(inputRow, inputExpressions, e)
}
}

Expand Down Expand Up @@ -238,21 +248,26 @@ case class ST_LineFromWKB(inputExpressions: Seq[Expression])
if (inputExpressions.length > 1) inputExpressions(1).eval(inputRow).asInstanceOf[Int]
else -1

wkb match {
case geomString: UTF8String =>
// Parse UTF-8 encoded WKB string
val geom = Constructors.lineStringFromText(geomString.toString, "wkb")
if (geom.getGeometryType == "LineString") {
(if (srid != -1) Functions.setSRID(geom, srid) else geom).toGenericArrayData
} else {
null
}

case wkbArray: Array[Byte] =>
// Convert raw WKB byte array to geometry
Constructors.lineFromWKB(wkbArray, srid).toGenericArrayData

case _ => null
try {
wkb match {
case geomString: UTF8String =>
// Parse UTF-8 encoded WKB string
val geom = Constructors.lineStringFromText(geomString.toString, "wkb")
if (geom.getGeometryType == "LineString") {
(if (srid != -1) Functions.setSRID(geom, srid) else geom).toGenericArrayData
} else {
null
}

case wkbArray: Array[Byte] =>
// Convert raw WKB byte array to geometry
Constructors.lineFromWKB(wkbArray, srid).toGenericArrayData

case _ => null
}
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(inputRow, inputExpressions, e)
}
}

Expand Down Expand Up @@ -287,21 +302,26 @@ case class ST_LinestringFromWKB(inputExpressions: Seq[Expression])
if (inputExpressions.length > 1) inputExpressions(1).eval(inputRow).asInstanceOf[Int]
else -1

wkb match {
case geomString: UTF8String =>
// Parse UTF-8 encoded WKB string
val geom = Constructors.lineStringFromText(geomString.toString, "wkb")
if (geom.getGeometryType == "LineString") {
(if (srid != -1) Functions.setSRID(geom, srid) else geom).toGenericArrayData
} else {
null
}

case wkbArray: Array[Byte] =>
// Convert raw WKB byte array to geometry
Constructors.lineFromWKB(wkbArray, srid).toGenericArrayData

case _ => null
try {
wkb match {
case geomString: UTF8String =>
// Parse UTF-8 encoded WKB string
val geom = Constructors.lineStringFromText(geomString.toString, "wkb")
if (geom.getGeometryType == "LineString") {
(if (srid != -1) Functions.setSRID(geom, srid) else geom).toGenericArrayData
} else {
null
}

case wkbArray: Array[Byte] =>
// Convert raw WKB byte array to geometry
Constructors.lineFromWKB(wkbArray, srid).toGenericArrayData

case _ => null
}
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(inputRow, inputExpressions, e)
}
}

Expand Down Expand Up @@ -336,21 +356,26 @@ case class ST_PointFromWKB(inputExpressions: Seq[Expression])
if (inputExpressions.length > 1) inputExpressions(1).eval(inputRow).asInstanceOf[Int]
else -1

wkb match {
case geomString: UTF8String =>
// Parse UTF-8 encoded WKB string
val geom = Constructors.pointFromText(geomString.toString, "wkb")
if (geom.getGeometryType == "Point") {
(if (srid != -1) Functions.setSRID(geom, srid) else geom).toGenericArrayData
} else {
null
}

case wkbArray: Array[Byte] =>
// Convert raw WKB byte array to geometry
Constructors.pointFromWKB(wkbArray, srid).toGenericArrayData

case _ => null
try {
wkb match {
case geomString: UTF8String =>
// Parse UTF-8 encoded WKB string
val geom = Constructors.pointFromText(geomString.toString, "wkb")
if (geom.getGeometryType == "Point") {
(if (srid != -1) Functions.setSRID(geom, srid) else geom).toGenericArrayData
} else {
null
}

case wkbArray: Array[Byte] =>
// Convert raw WKB byte array to geometry
Constructors.pointFromWKB(wkbArray, srid).toGenericArrayData

case _ => null
}
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(inputRow, inputExpressions, e)
}
}

Expand Down Expand Up @@ -387,12 +412,18 @@ case class ST_GeomFromGeoJSON(inputExpressions: Seq[Expression])

override def eval(inputRow: InternalRow): Any = {
val geomString = inputExpressions.head.eval(inputRow).asInstanceOf[UTF8String].toString
val geometry = Constructors.geomFromText(geomString, FileDataSplitter.GEOJSON)
// If the user specify a bunch of attributes to go with each geometry, we need to store all of them in this geometry
if (inputExpressions.length > 1) {
geometry.setUserData(generateUserData(minInputLength, inputExpressions, inputRow))
try {

val geometry = Constructors.geomFromText(geomString, FileDataSplitter.GEOJSON)
// If the user specify a bunch of attributes to go with each geometry, we need to store all of them in this geometry
if (inputExpressions.length > 1) {
geometry.setUserData(generateUserData(minInputLength, inputExpressions, inputRow))
}
GeometrySerializer.serialize(geometry)
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(inputRow, inputExpressions, e)
}
GeometrySerializer.serialize(geometry)
}

override def dataType: DataType = GeometryUDT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,13 +332,18 @@ case class ST_IsValidDetail(children: Seq[Expression])
throw new IllegalArgumentException(s"Invalid number of arguments: $nArgs")
}

if (validDetail.location == null) {
return InternalRow.fromSeq(Seq(validDetail.valid, null, null))
}
try {
if (validDetail.location == null) {
return InternalRow.fromSeq(Seq(validDetail.valid, null, null))
}

val serLocation = GeometrySerializer.serialize(validDetail.location)
InternalRow.fromSeq(
Seq(validDetail.valid, UTF8String.fromString(validDetail.reason), serLocation))
val serLocation = GeometrySerializer.serialize(validDetail.location)
InternalRow.fromSeq(
Seq(validDetail.valid, UTF8String.fromString(validDetail.reason), serLocation))
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(input, children, e)
}
}

protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]): Expression = {
Expand Down Expand Up @@ -609,14 +614,20 @@ case class ST_MinimumBoundingRadius(inputExpressions: Seq[Expression])

override def eval(input: InternalRow): Any = {
val expr = inputExpressions(0)
val geometry = expr match {
case s: SerdeAware => s.evalWithoutSerialization(input)
case _ => expr.toGeometry(input)
}

geometry match {
case geometry: Geometry => getMinimumBoundingRadius(geometry)
case _ => null
try {
val geometry = expr match {
case s: SerdeAware => s.evalWithoutSerialization(input)
case _ => expr.toGeometry(input)
}

geometry match {
case geometry: Geometry => getMinimumBoundingRadius(geometry)
case _ => null
}
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(input, inputExpressions, e)
}
}

Expand Down Expand Up @@ -910,17 +921,23 @@ case class ST_SubDivideExplode(children: Seq[Expression]) extends Generator with
override def eval(input: InternalRow): TraversableOnce[InternalRow] = {
val geometryRaw = children.head
val maxVerticesRaw = children(1)
geometryRaw.toGeometry(input) match {
case geom: Geometry =>
ArrayData.toArrayData(
Functions.subDivide(geom, maxVerticesRaw.toInt(input)).map(_.toGenericArrayData))
Functions
.subDivide(geom, maxVerticesRaw.toInt(input))
.map(_.toGenericArrayData)
.map(InternalRow(_))
case _ => new Array[InternalRow](0)
try {
geometryRaw.toGeometry(input) match {
case geom: Geometry =>
ArrayData.toArrayData(
Functions.subDivide(geom, maxVerticesRaw.toInt(input)).map(_.toGenericArrayData))
Functions
.subDivide(geom, maxVerticesRaw.toInt(input))
.map(_.toGenericArrayData)
.map(InternalRow(_))
case _ => new Array[InternalRow](0)
}
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(input, children, e)
}
}

override def elementSchema: StructType = {
new StructType()
.add("geom", GeometryUDT, true)
Expand Down Expand Up @@ -978,13 +995,18 @@ case class ST_MaximumInscribedCircle(children: Seq[Expression])
with CodegenFallback {

override def eval(input: InternalRow): Any = {
val geometry = children.head.toGeometry(input)
var inscribedCircle: InscribedCircle = null
inscribedCircle = Functions.maximumInscribedCircle(geometry)

val serCenter = GeometrySerializer.serialize(inscribedCircle.center)
val serNearest = GeometrySerializer.serialize(inscribedCircle.nearest)
InternalRow.fromSeq(Seq(serCenter, serNearest, inscribedCircle.radius))
try {
val geometry = children.head.toGeometry(input)
var inscribedCircle: InscribedCircle = null
inscribedCircle = Functions.maximumInscribedCircle(geometry)

val serCenter = GeometrySerializer.serialize(inscribedCircle.center)
val serNearest = GeometrySerializer.serialize(inscribedCircle.nearest)
InternalRow.fromSeq(Seq(serCenter, serNearest, inscribedCircle.radius))
} catch {
case e: Exception =>
InferredExpression.throwExpressionInferenceException(input, children, e)
}
}

protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]): Expression = {
Expand Down
Loading
Loading