This commit is contained in:
jilen 2024-11-14 19:46:36 +08:00
parent 1878d59821
commit 2d30969ec5
5 changed files with 68 additions and 70 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
target/
.bsp/
.metals/
.bloop/
project/metals.sbt

View file

@ -1 +1 @@
sbt.version=1.10.2
sbt.version=1.10.5

View file

@ -0,0 +1,8 @@
// format: off
// DO NOT EDIT! This file is auto-generated.
// This file enables sbt-bloop to create bloop config files.
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.6.0")
// format: on

View file

@ -81,16 +81,16 @@ case class ConcatMap(query: Ast, alias: Ident, body: Ast) extends Query
case class SortBy(query: Ast, alias: Ident, criterias: Ast, ordering: Ordering)
extends Query
sealed trait Ordering extends Ast
sealed trait Ordering extends Ast
case class TupleOrdering(elems: List[Ordering]) extends Ordering
sealed trait PropertyOrdering extends Ordering
case object Asc extends PropertyOrdering
case object Desc extends PropertyOrdering
case object AscNullsFirst extends PropertyOrdering
case object DescNullsFirst extends PropertyOrdering
case object AscNullsLast extends PropertyOrdering
case object DescNullsLast extends PropertyOrdering
case object Asc extends PropertyOrdering
case object Desc extends PropertyOrdering
case object AscNullsFirst extends PropertyOrdering
case object DescNullsFirst extends PropertyOrdering
case object AscNullsLast extends PropertyOrdering
case object DescNullsLast extends PropertyOrdering
case class GroupBy(query: Ast, alias: Ident, body: Ast) extends Query
@ -154,7 +154,7 @@ case class Ident(name: String, visibility: Visibility) extends Ast {
*/
object Ident {
def apply(name: String): Ident = Ident(name, Visibility.neutral)
def unapply(p: Ident) = Some((p.name))
def unapply(p: Ident) = Some((p.name))
object Opinionated {
def apply(name: String, visibilityNew: Visibility): Ident =
@ -188,7 +188,7 @@ sealed trait OpinionValues[T <: Opinion[T]] {
sealed trait Visibility extends Opinion[Visibility]
object Visibility extends OpinionValues[Visibility] {
case object Visible extends Visibility with Opinion[Visibility]
case object Hidden extends Visibility with Opinion[Visibility]
case object Hidden extends Visibility with Opinion[Visibility]
inline override def neutral: Visibility = Visible
}
@ -201,7 +201,7 @@ sealed trait Renameable extends Opinion[Renameable] {
}
}
object Renameable extends OpinionValues[Renameable] {
case object Fixed extends Renameable with Opinion[Renameable]
case object Fixed extends Renameable with Opinion[Renameable]
case object ByStrategy extends Renameable with Opinion[Renameable]
inline override def neutral: Renameable = ByStrategy
@ -248,8 +248,8 @@ object Property {
}
}
sealed trait OptionOperation extends Ast
case class OptionFlatten(ast: Ast) extends OptionOperation
sealed trait OptionOperation extends Ast
case class OptionFlatten(ast: Ast) extends OptionOperation
case class OptionGetOrElse(ast: Ast, body: Ast) extends OptionOperation
case class OptionFlatMap(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
@ -259,9 +259,9 @@ case class OptionForall(ast: Ast, alias: Ident, body: Ast)
case class OptionExists(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
case class OptionContains(ast: Ast, body: Ast) extends OptionOperation
case class OptionIsEmpty(ast: Ast) extends OptionOperation
case class OptionNonEmpty(ast: Ast) extends OptionOperation
case class OptionIsDefined(ast: Ast) extends OptionOperation
case class OptionIsEmpty(ast: Ast) extends OptionOperation
case class OptionNonEmpty(ast: Ast) extends OptionOperation
case class OptionIsDefined(ast: Ast) extends OptionOperation
case class OptionTableFlatMap(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
case class OptionTableMap(ast: Ast, alias: Ident, body: Ast)
@ -270,15 +270,15 @@ case class OptionTableExists(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
case class OptionTableForall(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
object OptionNone extends OptionOperation
case class OptionSome(ast: Ast) extends OptionOperation
case class OptionApply(ast: Ast) extends OptionOperation
case class OptionOrNull(ast: Ast) extends OptionOperation
object OptionNone extends OptionOperation
case class OptionSome(ast: Ast) extends OptionOperation
case class OptionApply(ast: Ast) extends OptionOperation
case class OptionOrNull(ast: Ast) extends OptionOperation
case class OptionGetOrNull(ast: Ast) extends OptionOperation
sealed trait IterableOperation extends Ast
case class MapContains(ast: Ast, body: Ast) extends IterableOperation
case class SetContains(ast: Ast, body: Ast) extends IterableOperation
sealed trait IterableOperation extends Ast
case class MapContains(ast: Ast, body: Ast) extends IterableOperation
case class SetContains(ast: Ast, body: Ast) extends IterableOperation
case class ListContains(ast: Ast, body: Ast) extends IterableOperation
case class If(condition: Ast, `then`: Ast, `else`: Ast) extends Ast
@ -318,7 +318,7 @@ sealed trait Action extends Ast
case class Update(query: Ast, assignments: List[Assignment]) extends Action
case class Insert(query: Ast, assignments: List[Assignment]) extends Action
case class Delete(query: Ast) extends Action
case class Delete(query: Ast) extends Action
sealed trait ReturningAction extends Action {
def action: Ast
@ -358,11 +358,11 @@ object OnConflict {
}
sealed trait Target
case object NoTarget extends Target
case object NoTarget extends Target
case class Properties(props: List[Property]) extends Target
sealed trait Action
case object Ignore extends Action
case object Ignore extends Action
case class Update(assignments: List[Assignment]) extends Action
}
//************************************************************
@ -386,34 +386,15 @@ sealed trait ScalarLift extends Lift
case class ScalarValueLift(
name: String,
liftId: String
) extends ScalarLift {
def expandedLiftId: Option[(String, Int)] = {
val idxStart = liftId.indexOf('[')
val idxEnd = liftId.indexOf(']')
if (idxStart != -1 && idxEnd != -1) {
val idx = liftId.substring(idxStart + 1, idxEnd).toIntOption
idx.map(i => liftId.substring(0, idxStart) -> i)
} else None
}
}
case class ScalarQueryLift(name: String, liftId: String) extends ScalarLift {
def at(idx: Int): ScalarValueLift =
ScalarValueLift(s"${name}[$idx]", s"${liftId}[${idx}]")
}
) extends ScalarLift
object ScalarLift {
given ToExpr[ScalarLift] with {
def apply(l: ScalarLift)(using Quotes) = l match {
case ScalarValueLift(n, id) =>
'{ ScalarValueLift(${ Expr(n) }, ${ Expr(id) }) }
case ScalarQueryLift(n, id) =>
'{ ScalarQueryLift(${ Expr(n) }, ${ Expr(id) }) }
}
}
}
sealed trait CaseClassLift extends Lift
case class CaseClassQueryLift(name: String, liftId: String)
extends CaseClassLift

View file

@ -1,39 +1,46 @@
package minisql.dsl
import minisql.ast.{Ast, Entity, given}
import scala.quoted.*
import scala.compiletime.*
import scala.compiletime.ops.string.*
trait Quoted[E] {
type Ast
sealed trait Dsl {
def ast: Ast
def liftings: Map[String, Any]
}
object Quoted {
def apply[_Ast <: String, E](
_ast: Ast,
_liftings: Map[String, Any]
): Quoted[_Ast, E] =
new Quoted[_Ast] {
type Ast = _Ast
def ast = _ast
def liftings = _liftings
trait Query[E] extends Dsl
class EntityQuery[E](val ast: Ast) extends Query
given FromExpr[EntityQuery[?]] with {
def unapply(x: Expr[EntityQuery[?]])(using Quotes): Option[EntityQuery[?]] = {
x match {
case '{ EntityQuery(${ Expr(ast) }) } =>
Some(EntityQuery(ast))
case _ =>
import quotes.reflect.*
println(s"cannot unlift ${x.asTerm}")
None
}
inline def transform[A1 <: String, A2 <: String, A3 <: String](
inline q1: Quoted[A1],
inline q2: Quoted[A2]
)(inline f: (A1, A2) => A3): Quoted[A3] =
Quoted[A3](q1.liftings ++ q2.liftings)
}
}
given FromExpr[Dsl] with {
def unapply(d: Expr[Dsl])(using Quotes): Option[Dsl] = d match {
case '{ ($x: EntityQuery[?]) } => x.value
}
}
case class Foo()
inline def query[E](inline table: String) =
EntityQuery[E](Entity(table, Nil))
opaque type Query[E] <: Quoted[E] = Quoted[E]
opaque type EntityQuery[E] <: Quoted[E] & Query[E] = Quoted[E]
inline def compile(inline x: Dsl): Option[String] = ${ compileImpl('x) }
private def compileImpl(x: Expr[Dsl])(using Quotes): Expr[Option[String]] = {
import quotes.reflect.*
x.value match {
case Some(xv) => '{ Some(${ Expr(xv.ast.toString()) }) }
case None => '{ None }
}
extension [E](e: EntityQuery[E]) {
inline def map[E1](inline f: E => E1): EntityQuery[E1] = Quoted[]()
}