Skip to content

Commit

Permalink
fix: [~] child dynamic accessor only for struct columns (issue #265) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
eruizalo committed Feb 3, 2023
1 parent a4cd92a commit 1fd8884
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 19 deletions.
4 changes: 1 addition & 3 deletions core/src/main/scala/doric/DoricColumn.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@ import doric.syntax.ColGetters
import doric.types.{LiteralSparkType, SparkType}

import org.apache.spark.sql.{Column, Dataset}
import org.apache.spark.sql.catalyst.CatalystTypeConverters
import org.apache.spark.sql.catalyst.analysis.UnresolvedAttribute
import org.apache.spark.sql.catalyst.expressions.Literal
import org.apache.spark.sql.types.DataType

sealed trait DoricColumn[T] extends DynamicFieldAccessor[T] {
sealed trait DoricColumn[T] {
val elem: Doric[Column]
}

Expand Down
19 changes: 9 additions & 10 deletions core/src/main/scala/doric/syntax/DStructs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ private[syntax] trait DStructs {
) {

/**
* Retreaves the child row of the Struct column
* Retrieves the child row of the Struct column
*
* @group Struct Type
* @param subColumnName
Expand Down Expand Up @@ -85,10 +85,13 @@ private[syntax] trait DStructs {
.mapK(toValidated)
.toDC
}

def child: DynamicFieldAccessor[T] = new DynamicFieldAccessor(col)
}

trait DynamicFieldAccessor[T] extends Dynamic {
self: DoricColumn[T] =>
class DynamicFieldAccessor[T](dCol: DoricColumn[T])(implicit
st: SparkType.Custom[T, Row]
) extends Dynamic {

/**
* Allows for accessing fields of struct columns using the syntax `rowcol.name[T]`.
Expand All @@ -101,13 +104,9 @@ private[syntax] trait DStructs {
* @return The column which refers to the given field
* @throws doric.sem.ColumnTypeError if the parent column is not a struct
*/

def selectDynamic[A](name: String)(implicit
location: Location,
st: SparkType[A],
w: T Is Row
): DoricColumn[A] =
w.lift[DoricColumn].coerce(self).getChild[A](name)
def selectDynamic[A: SparkType](name: String)(implicit
location: Location
): DoricColumn[A] = dCol.getChild[A](name)
}

@annotation.implicitNotFound(msg = "No field ${K} in record ${L}")
Expand Down
15 changes: 9 additions & 6 deletions core/src/test/scala/doric/syntax/DynamicSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,29 @@ class DynamicSpec extends DoricTestElements with EitherValues with Matchers {
describe("Dynamic invocations") {

it("can get values from sub-columns of `Row`` columns") {
df.validateColumnType(colStruct("user").name[String])
df.validateColumnType(colStruct("user").age[Int])
colStruct("user").child.name[String]
df.validateColumnType(colStruct("user").child.name[String])
df.validateColumnType(colStruct("user").child.age[Int])
}

it("can get values from sub-sub-columns") {
List(((("1", 2.0), 2), true))
.toDF()
.validateColumnType(colStruct("_1")._1[Row]._1[String])
.validateColumnType(colStruct("_1").child._1[Row].child._1[String])
}

it("can get values from the top-level row") {
df.validateColumnType(row.user[Row])
df.validateColumnType(row.user[Row].age[Int])
df.validateColumnType(row.user[Row].child.age[Int])
List(("1", 2, true)).toDF().validateColumnType(row._1[String])
List((("1", 2), true)).toDF().validateColumnType(row._1[Row]._2[Int])
List((("1", 2), true))
.toDF()
.validateColumnType(row._1[Row].child._2[Int])
}

if (minorScalaVersion >= 12)
it("should not compile if the parent column is not a row") {
"""val c: DoricColumn[String] = col[Int]("id").name[String]""" shouldNot compile
"""val c: DoricColumn[String] = col[Int]("id").child.name[String]""" shouldNot compile
}
}
}

0 comments on commit 1fd8884

Please sign in to comment.