2017-11-25 1 views
0

Relevant Schnipsel zur Laufzeit auf Syntaxfehler abstürzt:Abfrage in Quill

case class Video(
    id: String, 
    title: String, 
    url: String, 
    pictureUrl: String, 
    publishedAt: Date, 
    channel: String, 
    duration: Option[String], 
    createdOn: Date 
) 

"Verbindung" an die DB arbeitet, die Auswahl von Video-Returns Tabelle erwarteten Ergebnisse. Ich habe ein Problem mit dem Speichern, diese einfache Methode:

def saveToCache(item: Video): Unit = { 
    logger.trace(item) 
    import ctx._ 
    val x = quote { 
     val lItem = lift(item) 
     val fromDb = query[Video].filter(_.id == lItem.id) 
     if (fromDb.isEmpty) query[Video].insert(lItem) 
     else fromDb.update(lItem) 
    } 
    logger.trace(x.ast) 
    run(x) 
    } 

Abstürze zur Laufzeit mit (verkürzt):

11:14:06.640 [scala-execution-context-global-84] ERROR io.udash.rpc.AtmosphereService - RPC request handling failed 
org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (near "CASE": syntax error) 
     at org.sqlite.core.DB.newSQLException(DB.java:909) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.core.DB.newSQLException(DB.java:921) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.core.DB.throwex(DB.java:886) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.core.NativeDB.prepare_utf8(Native Method) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.core.NativeDB.prepare(NativeDB.java:127) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.core.DB.prepare(DB.java:227) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.core.CorePreparedStatement.<init>(CorePreparedStatement.java:41) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.jdbc3.JDBC3PreparedStatement.<init>(JDBC3PreparedStatement.java:30) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.jdbc4.JDBC4PreparedStatement.<init>(JDBC4PreparedStatement.java:19) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.jdbc4.JDBC4Connection.prepareStatement(JDBC4Connection.java:48) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:263) ~[sqlite-jdbc-3.18.0.jar:na] 
     at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:235) ~[sqlite-jdbc-3.18.0.jar:na] 
     at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:317) ~[HikariCP-2.7.2.jar:na] 
     at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java) ~[HikariCP-2.7.2.jar:na] 
     at io.getquill.context.jdbc.JdbcContext.$anonfun$executeAction$1(JdbcContext.scala:98) ~[quill-jdbc_2.12-2.2.0.jar:2.2.0] 
     at io.getquill.context.jdbc.JdbcContext.$anonfun$executeAction$1$adapted(JdbcContext.scala:97) ~[quill-jdbc_2.12-2.2.0.jar:2.2.0] 
     at io.getquill.context.jdbc.JdbcContext.$anonfun$withConnection$1(JdbcContext.scala:46) ~[quill-jdbc_2.12-2.2.0.jar:2.2.0] 
     at scala.Option.getOrElse(Option.scala:121) ~[scala-library-2.12.2.jar:1.0.0-M1] 
     at io.getquill.context.jdbc.JdbcContext.withConnection(JdbcContext.scala:44) ~[quill-jdbc_2.12-2.2.0.jar:2.2.0] 
     at io.getquill.context.jdbc.JdbcContext.executeAction(JdbcContext.scala:97) ~[quill-jdbc_2.12-2.2.0.jar:2.2.0] 

Relevante Ausgabe von Makro während der Kompilierung:

CASE WHEN NOT EXISTS (SELECT x3.* FROM video x3 WHERE x3.id = ?) THEN INSERT INTO video (id,title,url,picture_url,published_at,channel,duration,created_on) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ELSE UPDATE video SET id = ?, title = ?, url = ?, picture_url = ?, published_at = ?, channel = ?, duration = ?, created_on = ? WHERE id = ? END 

Ich wollte Aktivieren Sie die Protokollierung von Abfragen, aber ich habe keine Ahnung, wie es geht (Quill-Dokumente sagen nur etwas über SLF4J, was nutzlose Informationen für mich sind - ich sehe keine Protokolle und weiß nicht, wonach ich in SLF4J suchen soll. d ocs).

Bisher bin ich ziemlich enttäuscht von Quill - das erste Mal erzeugt es ungültige Abfrage für die Bestellung bei Verwendung der Standard-Bestellart und jetzt dies.

+0

Ich habe Fehler in meiner Antwort behoben und Informationen zur Protokollierung hinzugefügt. – mixel

Antwort

0

Sie sollten Sie umschreiben Abfrage wie:

import ctx._ 
def saveToCache(item: Video): Unit = { 
    if (ctx.run(query[Video].filter(_.id == lift(item.id)).isEmpty)) 
    ctx.run(query[Video].insert(lift(item))) 
    else ctx.run(query[Video].filter(_.id == lift(item.id)).update(lift(item))) 
() 
} 

weil quote Ausdruck enthalten muss, die zu einer einzigen Abfrage erstellt werden. Dieser Code wird zu drei Abfragen kompiliert.

Aber eine bessere Nutzung optimierte Version:

import ctx._ 
def saveToCacheOptimized(item: Video): Unit = { 
    if (ctx.run(query[Video].filter(_.id == lift(item.id)).update(lift(item))) == 0) 
    ctx.run(query[Video].insert(lift(item))) 
() 
} 

, die zu zwei Abfragen erstellt.

Pinole verwendet SLF4J für die Protokollierung, sollten Sie diese Projektdokumentation lesen. So aktivieren Sie die Anmeldung sollten Sie einige Protokollierung Backend hinzufügen, zum Beispiel logback:

libraryDependencies ++= Seq(
    "ch.qos.logback" % "logback-classic" % "1.2.3" 
) 

Es sollte nur protokolliert immer Abfragen genug sein.

+0

Danke, es funktioniert :). Ich habe wahrscheinlich zu viel von Quill erwartet, vielleicht weil ich ein paar Jahre mit ORMs gearbeitet habe. Aber Quill scheint der DB-Schicht viel näher zu sein und ist nicht so narrensicher, wie ich es mir erhofft hatte (Regel "wenn es kompiliert" ist klar, hält hier nicht, sogar bei korrekten Typen, bei denen es scheitern könnte) Laufzeit). – monnef

+0

Eigentlich scheint es ein Fehler zu sein. Ich habe es gemeldet (https://github.com/getquill/quill/issues/974). – mixel