Skip to content

Commit 5a6005b

Browse files
Michał PałkaMichał Pałka
authored andcommitted
Introduce ColumnFuns
1 parent 540ede8 commit 5a6005b

22 files changed

+399
-234
lines changed

src/main/CollectColumns.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,3 @@ object CollectColumns:
2828
new CollectColumns[H *: T]:
2929
type CollectedColumns = Tuple.Concat[collectHead.CollectedColumns, collectTail.CollectedColumns]
3030
def underlyingColumns(c: H *: T) = collectHead.underlyingColumns(c.head) ++ collectTail.underlyingColumns(c.tail)
31-
32-
33-
// TODO Customize error message for different operations with an explanation
34-
class CannotCollectColumns(typeName: String)
35-
extends Exception(s"Could not find an instance of CollectColumns for ${typeName}")

src/main/Column.scala

Lines changed: 18 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,35 @@
11
package org.virtuslab.iskra
22

3-
import scala.language.implicitConversions
4-
53
import scala.quoted.*
64

75
import org.apache.spark.sql.{Column => UntypedColumn}
86
import types.DataType
97
import MacroHelpers.TupleSubtype
108

11-
class Column(val untyped: UntypedColumn):
12-
inline def name(using v: ValueOf[Name]): Name = v.value
9+
sealed class Column(val untyped: UntypedColumn) extends ColumnOps
1310

1411
object Column:
15-
implicit transparent inline def columnToNamedColumn(inline col: Col[?]): NamedColumn[?, ?] =
16-
${ columnToNamedColumnImpl('col) }
17-
18-
private def columnToNamedColumnImpl(col: Expr[Col[?]])(using Quotes): Expr[NamedColumn[?, ?]] =
19-
import quotes.reflect.*
20-
col match
21-
case '{ ($v: StructuralSchemaView).selectDynamic($nm: Name).$asInstanceOf$[Col[tp]] } =>
22-
nm.asTerm.tpe.asType match
23-
case '[Name.Subtype[n]] =>
24-
'{ NamedColumn[n, tp](${ col }.untyped.as(${ nm })) }
25-
case '{ $c: Col[tp] } =>
26-
col.asTerm match
27-
case Inlined(_, _, Ident(name)) =>
28-
ConstantType(StringConstant(name)).asType match
29-
case '[Name.Subtype[n]] =>
30-
val alias = Literal(StringConstant(name)).asExprOf[Name]
31-
'{ NamedColumn[n, tp](${ col }.untyped.as(${ alias })) }
12+
def unsafeTyped[R <: ColumnOrError](untyped: UntypedColumn): R = new ColumnImpl(untyped).asInstanceOf[R]
3213

3314
extension [T <: DataType](col: Col[T])
3415
inline def as[N <: Name](name: N): NamedColumn[N, T] =
3516
NamedColumn[N, T](col.untyped.as(name))
3617
inline def alias[N <: Name](name: N): NamedColumn[N, T] =
3718
NamedColumn[N, T](col.untyped.as(name))
3819

39-
extension [T1 <: DataType](col1: Col[T1])
40-
inline def +[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Plus[T1, T2]): Col[op.Out] = op(col1, col2)
41-
inline def -[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Minus[T1, T2]): Col[op.Out] = op(col1, col2)
42-
inline def *[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Mult[T1, T2]): Col[op.Out] = op(col1, col2)
43-
inline def /[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Div[T1, T2]): Col[op.Out] = op(col1, col2)
44-
inline def ++[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.PlusPlus[T1, T2]): Col[op.Out] = op(col1, col2)
45-
inline def <[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Lt[T1, T2]): Col[op.Out] = op(col1, col2)
46-
inline def <=[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Le[T1, T2]): Col[op.Out] = op(col1, col2)
47-
inline def >[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Gt[T1, T2]): Col[op.Out] = op(col1, col2)
48-
inline def >=[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Ge[T1, T2]): Col[op.Out] = op(col1, col2)
49-
inline def ===[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Eq[T1, T2]): Col[op.Out] = op(col1, col2)
50-
inline def =!=[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Ne[T1, T2]): Col[op.Out] = op(col1, col2)
51-
inline def &&[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.And[T1, T2]): Col[op.Out] = op(col1, col2)
52-
inline def ||[T2 <: DataType](col2: Col[T2])(using op: ColumnOp.Or[T1, T2]): Col[op.Out] = op(col1, col2)
20+
export ColumnOps.*
21+
export ColumnOps.given
22+
23+
final class DataColumn(untyped: UntypedColumn) extends Column(untyped)
24+
25+
26+
// TODO: Get rid of covariance?
27+
sealed class Col[+T <: DataType](untyped: UntypedColumn) extends Column(untyped)
5328

29+
final class ColumnImpl(untyped: UntypedColumn) extends Col[Nothing](untyped)
5430

55-
class Col[+T <: DataType](untyped: UntypedColumn) extends Column(untyped)
31+
object ColumnImpl:
32+
def apply[R <: ColumnOrError](untyped: UntypedColumn): R = new ColumnImpl(untyped).asInstanceOf[R]
5633

5734

5835
object Columns:
@@ -72,23 +49,11 @@ object Columns:
7249
ColumnsWithSchema[collectedCols](cols)
7350
}
7451
case None =>
75-
throw CollectColumns.CannotCollectColumns(Type.show[C])
76-
77-
78-
trait NamedColumnOrColumnsLike
79-
80-
type NamedColumns = Repeated[NamedColumnOrColumnsLike]
81-
82-
class NamedColumn[N <: Name, T <: DataType](val untyped: UntypedColumn)
83-
extends NamedColumnOrColumnsLike
84-
85-
class ColumnsWithSchema[Schema <: Tuple](val underlyingColumns: Seq[UntypedColumn]) extends NamedColumnOrColumnsLike
86-
52+
// TODO: What should be returned here for best error messages?
53+
report.errorAndAbort("Cannot collect columns: " + Type.show[C])
8754

88-
@annotation.showAsInfix
89-
trait :=[L <: ColumnLabel, T <: DataType]
55+
type ColumnOrError = Column | ColumnError
9056

91-
@annotation.showAsInfix
92-
trait /[+Prefix <: Name, +Suffix <: Name]
57+
sealed trait ColumnError
9358

94-
type ColumnLabel = Name | (Name / Name)
59+
object ColumnError extends ColumnError

src/main/ColumnFun.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.virtuslab.iskra
2+
3+
import org.virtuslab.iskra.types.DataType
4+
5+
type AsColumnOrError[T] <: ColumnOrError = T match
6+
case DataType => Col[T]
7+
case _ => ColumnError
8+
9+
type ColumnFun1[C1 <: Column, F[_]] <: ColumnOrError = C1 match
10+
case Col[t1] => AsColumnOrError[F[t1]]
11+
case _ => ColumnError
12+
13+
14+
type ColumnFun2[C1 <: Column, C2 <: Column, F[_, _]] <: ColumnOrError = (C1, C2) match
15+
case (Col[t1], Col[t2]) => AsColumnOrError[F[t1, t2]]
16+
case _ => ColumnError

src/main/ColumnOp.scala

Lines changed: 0 additions & 138 deletions
This file was deleted.

0 commit comments

Comments
 (0)