diff --git a/src/main/scala/minisql/dsl.scala b/src/main/scala/minisql/dsl.scala index 43cc9c0..48191b3 100644 --- a/src/main/scala/minisql/dsl.scala +++ b/src/main/scala/minisql/dsl.scala @@ -7,28 +7,38 @@ import scala.quoted.* import scala.compiletime.* import scala.compiletime.ops.string.* import scala.collection.immutable.{Map => IMap} +import NamedTuple.AnyNamedTuple -opaque type Quoted <: Ast = Ast +opaque type Quoted[E] <: Ast = Ast -opaque type Query[E] <: Quoted = Quoted +opaque type Query[E <: AnyNamedTuple] <: Quoted[E] = Quoted[E] -opaque type EntityQuery[E] <: Query[E] = Query[E] +opaque type EntityQuery[E <: AnyNamedTuple] <: Query[E] = Query[E] -extension [E](inline e: EntityQuery[E]) { - inline def map[E1](inline f: E => E1): EntityQuery[E1] = { - transform(e)(f)(Map.apply) +opaque type Column[E] = Quoted[E] + +opaque type Row[X <: AnyNamedTuple] <: Quoted[X] = Quoted[X] + +type FieldType[X <: NamedTuple.AnyNamedTuple, K] = + (NamedTuple.Names[X], NamedTuple.DropNames[X]) match { + case (K *: ktail, v *: vtail) => v + case (k *: ktail, v *: vtail) => FieldType[ktail, vtail] + } + +extension [E <: NamedTuple.AnyNamedTuple](inline x: Row[E]) { + transparent inline def field[K <: Tuple.Union[NamedTuple.Names[E]] & String]( + inline k: K + ): Column[FieldType[E, K]] = + Property(x, k) +} +extension [E <: AnyNamedTuple](inline e: EntityQuery[E]) { + inline def map[E1 <: AnyNamedTuple]( + inline f: Row[E] => E1 + ): EntityQuery[E1] = { + Map(e, Ident("x"), f(Ident("x"))) } } -private inline def transform[A, B](inline q1: Quoted)( - inline f: A => B -)(inline fast: (Ast, Ident, Ast) => Ast): Quoted = { - fast(q1, f.param0, f.body) -} - -inline def query[E](inline table: String): EntityQuery[E] = - Entity(table, Nil) - inline def compile(inline x: Ast): Option[String] = ${ compileImpl('{ x }) } @@ -56,4 +66,7 @@ extension [A1, A2, B](inline f1: (A1, A2) => B) { case class Foo(id: Int) -inline def queryFooId = query[Foo]("foo").map(_.id) +inline def query[X](inline n: String): EntityQuery[NamedTuple.From[X]] = + Entity("Foo", Nil) + +inline def queryFooId = query[Foo]("foo").map(x => (id = x.field("id")))