Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • May 28 07:05
    renovate[bot] synchronize #2351
  • May 28 07:05

    renovate[bot] on configure

    Add renovate.json (compare)

  • May 27 20:39
    chriseteka edited #2502
  • May 27 20:39
    chriseteka edited #2502
  • May 27 20:38
    chriseteka synchronize #2502
  • May 27 20:19
    chriseteka synchronize #2502
  • May 27 20:06
    deusaquilus commented #2502
  • May 27 15:18
    chriseteka opened #2502
  • May 27 14:42

    deusaquilus on master

    Update README.md (compare)

  • May 27 14:34
    chriseteka commented #2463
  • May 27 14:31

    deusaquilus on master

    Implement filterIfDefined (#250… (compare)

  • May 27 14:30
    deusaquilus closed #2282
  • May 27 14:30
    deusaquilus closed #2501
  • May 27 14:07
    chriseteka synchronize #2501
  • May 27 13:37

    deusaquilus on reproduce_postgres_issue

    Reproducing issue (compare)

  • May 27 13:29
    deusaquilus commented #2501
  • May 27 11:25
    CLAassistant commented #1045
  • May 27 08:39
    justcoon commented #2052
  • May 27 07:05
    renovate[bot] edited #2351
  • May 27 07:04
    renovate[bot] synchronize #2351
N.S. Cutler
@godenji

If it helps, here's the error I'm hitting:

A mirror of the type E cannot be summoned. It is not a sum-type, a product-type, or a encodeable entity so it's fields cannot be understood in the structure-elaborator

That would be on the query.insert line above
N.S. Cutler
@godenji

Looks like only way is via code generation; here's a project that does just that:
https://github.com/ajozwik/quill-generic

Too bad, would be great if one were able to abstract away common CRUD operations without resorting to code generation. Guess this is a limitation of the macro based approach that Quill uses, very limited abstraction support.

Tom Reeve
@TRReeve
If you implement the macros on scala 3 you can likely get a decent lifetime out of them in fairness
N.S. Cutler
@godenji
Not sure what that means wrt being able to abstract away common CRUD operations in Quill, but if by the above you mean that macros will be long lived (i.e. non-experimental) in Scala 3, let's hope so -- Scala 2 to Scala 3 macro migration is not an easy task, and is part of what's hindering the ecosystem at large from migrating to Scala 3.
Vasileios Lampridis
@V-Lamp
Hi, I have a quick question on MappedEncoding:
If the DB type is string and the case class type is UUID as in the example, how does it know the DB type at compile time so to use the implicit?
Vasileios Lampridis
@V-Lamp
Given the the DB type is not encoded somewhere as far as I understand
John Ewart
@johnewart
I recently discovered quill - so first of all <3 thanks for creating an awesome library! I did hit what appears to be a non-obvious issue: it seems that you can't use a case class with more than 15 fields - I worked around it eventually (just encoding / decoding JSON I don't need to query) but the initial error was to complain that there was no implicit InsertMeta (so I tried writing my own which failed spectacularly for other reasons). Is this a known issue / documented somewhere? I couldn't find anything that mentions this
Alexander Ioffe
@deusaquilus
@godenji I asked Martin this exact question at the Scala 3 release party. I.e. in another 8 years am I going to have to write the whole thing over again. His answer is similar to yours. Namely, that Scala 3 macros have a much stronger theoretical foundation from MetaML and are based on the Tasty format as opposed to directly being exposed to compiler internals.
Also, it should be possible to create something like quill-generic in Scala 3. It's just a matter of time and labor.
@V-Lamp I'm confused. Is the field of the case class a UUID or a string?
@johnewart I wasn't aware of such a limitation. Can I see an example query?
N.S. Cutler
@godenji

@deusaquilus

Also, it should be possible to create something like quill-generic in Scala 3. It's just a matter of time and labor.

Proto Quill basically has a bus factor of 1 (you being the 1 :)), so the nice-to-haves might not come soon enough for those looking to use proto Quill in the near-term. Saying that, I noticed yesterday that there's a code generator for Quill that could be used to generate DAO boilerplate without relying on an external library.

Hopefully Scala 3 macros will be able to replicate full Scala 2 Quill feature set without too many workarounds/concessions required.

Impressive work, btw, you've clearly taken the deep dive into Scala 3 macros (just testing the waters here now)

Alexander Ioffe
@deusaquilus
@godenji I'm hoping the bus-factor isn't quite 1. I've got a minimal-example implementation of Quill with Scala 3 macros (no lifts, no execution, etc...) called MiniQuill: https://github.com/deusaquilus/miniquill. This should at least explain how Quill in Scala 3 basically works. My YouTube series with the Drexel students goes through building up this example.
ProtoQuill was a long time coming. I've worked on it with Nicolas Stucki, Aggelos Bibodis, and others from early 2020. I've had to take a break from it for a couple months because the Quill ZIO context needed to be reworked in order to be a really great experience. Hopefully in the coming months I'll be able to get back into it. Also, if there is desire, I can give a series of public deep-dives on ProtoQuill.
N.S. Cutler
@godenji

Any resources the community can access that reveal the inner workings of the Scala 3 compiler vis-a-vis macros would be greatly appreciated. Through much trial and error, tree printing, etc. I managed to convert a complex (for me) Scala 2 macro to the Scala 3 equivalent. Learned a lot in the process but it was more challenging than it needed to be. If we had thorough documentation and real world examples to work from, the Scala 2 to Scala 3 macro migration would go much more smoothly, not to mention faster.

At any rate Quill is the gold standard of Scala 2/3 macros.

Also, in regard to implicit conversion from case class companion object Foo to query[Foo], I suspect that until lampepfl/dotty#7000 is resolved, getting that functionality working in Scala 3 will be quite the challenge. Basically flying blind, all you get with Foo.join(x => ...) at the macro level is a measely Product, no companion object Mirror, no case class ClassDef, nada.

Alexander Ioffe
@deusaquilus
What happens when you do?
inline given conv[T]: Conversion[T.type, Query[T]] = query[T]
Alexander Ioffe
@deusaquilus
Also @godenji, try this:
extension [T](inline ent: T.type)
  inline def insert(inline f: (T => (Any, Any)), inline f2: (T => (Any, Any))*): Insert[T] = query[T].insert(f, f2: _*)
  inline def update(inline f: (T => (Any, Any)), inline f2: (T => (Any, Any))*): Update[T] = query[T].update(f, f2: _*)
  inline def insert(inline value: T): Insert[T] = query[T].insert(value)
  inline def update(inline value: T): Update[T] = query[T].update(value)
  inline def map[R](f: T => R): Query[R] = query[T].map(f)
  inline def flatMap[R](f: T => Query[R]): Query[R] = query[T].flatMap(f)
  inline def concatMap[R, U](f: T => U)(implicit ev: U => Iterable[R]): Query[R] = query[T].concatMap(f)
  inline def withFilter(f: T => Boolean): Query[T] = query[T].withFilter(f)
  inline def filter(f: T => Boolean): Query[T] = query[T].filter(f)
  // etc... look into everything in Model.scala in regular-Quill
N.S. Cutler
@godenji

@deusaquilus T.type isn't valid scala syntax, but it would be convenient if it was :)

Examining scala 3 case class compiler generated source code in more detail, it's worse than I thought -- all we have to work with in the companion object is java.lang.Object, but still that's a start, can at least trigger macro invocation with static Foo.filter(...) call. From there I think we should be able to add a second type param to represent companion class T <: Product and check if it's a case class within body of macro; if not, error and abort, or else proceed with construction of (x: U) => query[T] Conversion[U, T] macro return type.

Siddhant Sanyam
@siddhant3s
Can someone help me understand the paper "Flatter the better" I've read it about half a dozen time now. I'm able to follow it through about half of it. But then I find myself totally lost when it comes to the Nested query part.
I have few pointed questions that would help me understand it better, which I can ask if someone feel comfortable with this paper
Oliver Breit
@obreit

i noticed a confusing (at least to me) behaviour when trying out quill with spark. i have this small example (scala=2.12.13,spark=3.1.2,quill=3.11.0)

import io.getquill.QuillSparkContext._
import io.getquill.Quoted
import org.apache.spark.sql.{Dataset, SQLContext}
import java.time.Instant

object TestQuill {

  implicit val instantEncoder: MappedEncoding[Long, Instant] = MappedEncoding[Long, Instant](Instant.ofEpochMilli)
  implicit val instantDecoder: MappedEncoding[Instant, Long] = MappedEncoding[Instant, Long](_.toEpochMilli)

  implicit class InstantQuotes(left: Instant) {
    def <(right: Instant): Quoted[Boolean] = quote(infix"$left < $right".as[Boolean])
  }

  implicit val sqlCtx: SQLContext = ???
  import sqlCtx.implicits._

  val ds: Dataset[Instant] = ???
  val ts: Instant = ???

  run {
    liftQuery(ds).filter(_ < lift(ts))
  }
}

if i specify the output type for the extention method explicitly def <(right: Instant): Quoted[Boolean] = ... it doesn't compile:

The query definition must happen within a `quote` block.
[error]     liftQuery(ds).filter(_ < lift(ts))
[error]                                  ^

if i leave out the type def <(right: Instant) = ...it compiles fine and generates the expected query.

i'm just curious if someone could explain this difference.

Grant
@gavares

I need to accept a dynmica list of sort fields and ordering as input and translate that into a database query. I’ve seen a number of questions around how to accomplish dynamic sortBy blocks but still haven’t seen a working example that doesn’t use infix to dynamically generate the ORDER BY section of a query. Has anyone managed to accoplish this or have an example?

I’ve managed something like this but it generates a nested SQL query for each element in my sortFields list rather than a single query with a single ORDER BY block:

val sortFields: Seq[SortField] = ???
val qry = myTable.filter(…)…..
sortFields.foldLeft(qry) { (q, field)  => 
   field match {
      case NameAsc   => q.sortBy(_.name)(Ord.Asc)
      case NameDesc => q.sortBy(_.name)(Ord.Desc)
      case IdAsc => q.sortBy(_.id)(Ord.Asc)
      case IdDesc => q.sortBy(_.id)(Ord.Desc)
      ...
   }
}
Grant
@gavares
I suppose the same question could be asked for how to dynamically select a list of columns from the table as well.
discobaba
@uncleweirdo_twitter
I would like to convert a project that is currently using torque to quill. It isn't small so I'm thinking of doing it a class or two at a time. Using 2 thread pools sounds looney, so I need to be able to get hold of a
Connection to support the old code. And to be able to get hold of it from within a transaction block, I should think ... Tips?
weili96
@weili96
Hi,Every one,I'm very happy.
Simon Parten
@Quafadas
I'm trying out protoquill and scala 3... seems to work well, but struggling with a couple of things...
Simon Parten
@Quafadas

Here's the route in the webserver, which is based on Akka http

      ~ path(IntNumber) { id =>
        concat(
          get(complete(Future(DB.aTodo(id)))),
          delete(complete(Future(DB.deleteTodo(id))))
        )

And here's the DB "implementation"

  val ctx = new PostgresJdbcContext(SnakeCase, new HikariDataSource(config))  
  import ctx._

def aTodo(id: Int) : Seq[Todo] = ctx.run { query[Todo].filter(_.todoId == lift(id)) }

  inline def updateTodo(todo: Todo) = ctx.run {
    query[Todo].filter(_.todoId == lift(todo.todoId)).update(lift(todo))
  }

Issue 1
Looking at the docs, the "canonical compile time" solution for aTodo would be inline def. If I do that, I get a message about "could not summon a parser factory, and cannot find a "scala.Int" Encoder of Id. So figured I leave that without the inline.

Issue 2

Simon Parten
@Quafadas
If the "updateTodo" is not inelin, then I get an "invalid transformation encountered, cannot find lift with ID: some_uuid
Does anyone have an idea what I might be doing wrong?
"io.getquill" %% "quill-jdbc" % "3.10.0.Beta1.6",
is the dependancy
Simon Parten
@Quafadas
Simon Parten
@Quafadas
and getquill/protoquill#22 :-)... my questions answered.
Александр Я.
@AlexYalinc_twitter

Hello guys. I just use

query[SomeClassWith15PlusColumns].insert(lift(data))

and quill say me:

Can't find an implicit `InsertMeta` for type `SomeClassWith15PlusColumns`
5 replies
How use case class with 15+ columns?
Александр Я.
@AlexYalinc_twitter
i use cassandra
dingcm
@d875708765
image.png
Alexander Ioffe
@deusaquilus
@d875708765 Where are you seeing this?
Jonathan Neufeld
@jonathan-neufeld-asurion

Hello all, I'm having trouble figuring out how to run multiple delete queries in a single transaction, any clues or pointers?

This was my naive starting point:

run {
  quote {
    query[TableOne]
      .delete
  } ::
  quote {
    query[TableTwo]
      .delete
  } :: Nil
}
weili96
@weili96
I love Quil!
Richard Michael Coo
@myknbani

Pardon me if it's a stupid question. Is it normal in Quill joins to return tuples, rather than say ORMish object graphs with say a one-to-many relationship?

From the looks of it, case classes represent table rows.

Andreas Frankenberger
@andyfr

Hi,
I would like to make use of the "insert on conflict update where is distinct from"-clause in Postgres in a generic fashion. Therefore I want to create a macro where I can write something like this:

case class Domains(id:Int, domain:String)
quote{
  insert[Domains](Domains(1, "a"), _.id)
}

Where the macro should be something like this:

def insert[A](row: A, idColumns: (A => Any)*): Insert[A] = macro InsertMacro.insertImpl[A]

def insertImpl[A: c.WeakTypeTag](c: Context)(row:c.Expr[A],idColumns:c.Expr[A => Any]*): c.universe.Tree= {
    import c.universe._
    val t=weakTypeOf[A]
    val r=q"""
          val q = query[$t].insert($row)
          val tableName = naming.table(${t.typeSymbol.name.toString})
          infix"$$q ON CONFLICT (id) DO UPDATE SET id = excluded.id WHERE (#$$tableName.*) IS DISTINCT FROM (excluded.*)".as[Insert[${t}]]
       """
    r
}

Unfortunately, the compile fails with Tree 'context.naming.table("Domains")' can't be parsed to 'Ast'.

Is there a way to translate the case class name to the table name and use it in the infix part within the quote{...} block?

Alexander Ioffe
@deusaquilus

@andyfr Is naming available at compile time? If so create the tableName variable in the macro & try something like this:

def insertImpl[A: c.WeakTypeTag](c: Context)(row:c.Expr[A],idColumns:c.Expr[A => Any]*): c.universe.Tree= {
    import c.universe._
    val t=weakTypeOf[A]
    val tableName = naming.table(t.typeSymbol.name.toString) 
    val r=q"""
          val q = query[$t].insert($row)
          infix"$$q ON CONFLICT (id) DO UPDATE SET id = excluded.id WHERE (${io.getquill.ast.EntityQuery($tableName)}.*) IS DISTINCT FROM (excluded.*)".as[Insert[${t}]]
       """
    r
}

That way you can splice the tableName into the query as a static string and the whole thing should be able to produce a compile-time query

2 replies
Alexander Ioffe
@deusaquilus
@/all We are moving this communication to the #zio-quill channel on the ZIO discord server here: https://discord.gg/2ccFBr4 and will soon close this channel.
Within the next couple of weeks I will look through the issues covered here and try to add relevant things to the Quill FAQ
(any help with this would be greatly appreciated, please let me know if you would like me to post on a specific question that has been asked in this thread).
rom1dep
@rom1dep:kde.org
[m]

Hello there!
I'm totally new to quill and playing a bit with proto-quill on top of a toy sqlite database, I can run simple queries fine but struggle with putting together joins,
here's the error I'm getting:

Main.scala:43:17: Exception occurred while executing macro expansion. scala.MatchError: TypedOrTest(Unapply(TypeApply(Select(Ident("Some"), "unapply"), List(Inferred())), Nil, List(Bind("it", Wildcard()))), Inferred()) (of class java.lang.String)

Here are my dependencies:

    ivy"org.xerial:sqlite-jdbc:3.36.0.3",
    ivy"io.getquill::quill-jdbc:3.17.0.Beta3.0-RC2"

and here is in substance the code

import io.getquill._
import io.getquill.QueryDsl.like

object Main {
  case class Artist(name: String)
  case class BuilderID(id: Int)
  case class Builder(id: BuilderID, name: String)
  case class InstrumentTypeID(id: Int)
  case class InstrumentType(id: InstrumentTypeID, description: String)
  case class InstrumentID(id: Int)
  case class Instrument(
      id: InstrumentID,
      typeId: InstrumentTypeID,
      builder: BuilderID,
      name: String
  )

val ctx = new SqliteJdbcContext(SnakeCase, "ctx")
  import ctx._

  def main(args: Array[String]): Unit = {

    inline def someInstruments = quote {
      query[Instrument]
        .leftJoin(query[InstrumentType])
        .on((i: Instrument, it: InstrumentType) => i.typeId == it.id)
        .filter({ case (i, Some(it)) => it.description.startsWith("Ukulele") })
        .map((i: Instrument, it: Option[InstrumentType]) => i)
    }
    println(run(someInstruments))
rom1dep
@rom1dep:kde.org
[m]

interestingly, it's seems to be an idiosyncratic thing

    inline def someInstruments = quote {
      query[Instrument]
        .leftJoin(query[InstrumentType])
        .on((i: Instrument, it: InstrumentType) => i.typeId == it.id)
        .filter(_._2.map(_.description.startsWith("Ukulele")).isDefined)
        .map((i: Instrument, _) => i.name)
    }

would work, on the other hand. So I guess one has to find a syntax that pleases the compiler and stick to it.

yanly007
@yanly007
Hello everyone,
Can someone please provide me with an example of a dynamic query containing joins. It just doesn't seem to work for me.
yanly007
@yanly007
So far I tried to use pattern matching and dynamicQuery but get quite a difficult to decipher error output
    val q = quote {
      for {
        user <- dynamicQuerySchema[User]("user")

        _ <- dynamicQuerySchema[UserToContract]("userToContrat").join { utc =>
          {
            contractIdOpt match {
              case Some(id) => quote(utc.contractId == lift(id))
              case None     => quote(true)
            }
          } && utc.userId == user.id
        }

      } yield user
    }
rom1dep
@rom1dep:kde.org
[m]
@yanly007: would something like that work?
quote {
      query[User]
        .join(query[UserToContract])
        .on((u: User, utc: UserToContract) => utc.contractId == lift(id) && utc.userId == u.id)
        //.map((u: User, _) => u)
    }