From 9f5c82d9bedce7bc3ef71c42736a3060b57f73c3 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 10 Apr 2022 11:32:34 -0400 Subject: [PATCH] Add UnaryDeserializer Either derivation support (#13) --- .../hiveless/serializers/UnaryDeserializer.scala | 12 ++++++++++-- .../main/scala/com/azavea/hiveless/utils/HShow.scala | 5 +++++ .../hiveless/spatial/index/ST_Intersects.scala | 2 ++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/com/azavea/hiveless/serializers/UnaryDeserializer.scala b/core/src/main/scala/com/azavea/hiveless/serializers/UnaryDeserializer.scala index a82c5f4..d2b7993 100644 --- a/core/src/main/scala/com/azavea/hiveless/serializers/UnaryDeserializer.scala +++ b/core/src/main/scala/com/azavea/hiveless/serializers/UnaryDeserializer.scala @@ -27,6 +27,7 @@ import cats.Id import cats.syntax.apply._ import org.apache.spark.sql.catalyst.encoders.ExpressionEncoder import org.apache.spark.sql.catalyst.util.ArrayData +import shapeless.ops.coproduct.{CoproductToEither, EitherToCoproduct} import shapeless.{:+:, CNil, Coproduct, HNil, Inl, Inr, IsTuple} import scala.reflect.ClassTag @@ -175,8 +176,15 @@ object UnaryDeserializer extends Serializable { Try(arrayDataUnaryDeserializer.deserialize(arguments, inspectors).toArray[T](HSerializer[T].dataType)) .getOrElse(nativeArrayUnaryDeserializer.deserialize(arguments, inspectors)) - /** Coproduct deserializer. */ - implicit def unaryDeserializerCCons[H, T <: Coproduct](implicit + /** Coproduct deserializers. */ + implicit def eitherUnaryDeserializer[L, R, P <: Coproduct](implicit + etp: EitherToCoproduct.Aux[L, R, P], + dp: UnaryDeserializer[Id, P], + pte: CoproductToEither.Aux[P, Either[L, R]] + ): UnaryDeserializer[Id, Either[L, R]] = + (arguments, inspectors) => pte(dp.deserialize(arguments, inspectors)) + + implicit def cconsUnaryDeserializer[H, T <: Coproduct](implicit dh: UnaryDeserializer[Id, H], dt: UnaryDeserializer[Id, T] ): UnaryDeserializer[Id, H :+: T] = diff --git a/core/src/main/scala/com/azavea/hiveless/utils/HShow.scala b/core/src/main/scala/com/azavea/hiveless/utils/HShow.scala index 555b98e..e17a062 100644 --- a/core/src/main/scala/com/azavea/hiveless/utils/HShow.scala +++ b/core/src/main/scala/com/azavea/hiveless/utils/HShow.scala @@ -16,6 +16,7 @@ package com.azavea.hiveless.utils +import shapeless.ops.coproduct.EitherToCoproduct import shapeless.{:+:, ::, CNil, Coproduct, Generic, HList, HNil, IsTuple} import scala.reflect.{classTag, ClassTag} @@ -32,6 +33,10 @@ object HShow extends LowPriorityHShow { implicit def hshowGeneric[T: IsTuple, L <: HList](implicit gen: Generic.Aux[T, L], sl: HShow[L]): HShow[T] = () => sl.show() + /** Derive HShow for Either. */ + implicit def hshowEither[L, R, P <: Coproduct](implicit etp: EitherToCoproduct.Aux[L, R, P], sp: HShow[P]): HShow[Either[L, R]] = + () => sp.show() + /** Derive HShow for HList. */ implicit val hshowHNil: HShow[HNil] = () => "" implicit def hshowHCons[H: ClassTag, T <: HList](implicit sh: HShow[H], st: HShow[T]): HShow[H :: T] = () => { diff --git a/spatial-index/src/main/scala/com/azavea/hiveless/spatial/index/ST_Intersects.scala b/spatial-index/src/main/scala/com/azavea/hiveless/spatial/index/ST_Intersects.scala index e2c7a63..8009633 100644 --- a/spatial-index/src/main/scala/com/azavea/hiveless/spatial/index/ST_Intersects.scala +++ b/spatial-index/src/main/scala/com/azavea/hiveless/spatial/index/ST_Intersects.scala @@ -31,6 +31,8 @@ class ST_Intersects extends HUDF[(ST_Intersects.Arg, ST_Intersects.Arg), Boolean object ST_Intersects { import UnaryDeserializer.Errors.ProductDeserializationError + // We could use Either[Extent, Geometry], but Either has no safe fall back CNil + // which may lead to derivation error messages rather than parsing type Arg = Extent :+: Geometry :+: CNil def parseGeometry(a: Arg): Option[Geometry] = a.select[Geometry].orElse(a.select[Extent].map(_.toPolygon()))