2017-11-25 131 views
0

相關片段:查詢在奎爾在運行時崩潰的語法錯誤

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

「連接」到DB工作,從預期的結果視頻臺返回選擇。我有儲蓄的問題,這個簡單的方法:

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) 
    } 

崩潰在運行時用(縮短):

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 

我想:

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] 

從宏觀編譯過程中相關的輸出

啓用日誌記錄查詢,但我不知道如何去做(Quill文檔只是說了一些關於SLF4J的信息,這對我來說是無用的信息 - 我沒有看到任何日誌,我不知道要在SLF4J中搜索什麼內容OCS)。

到目前爲止,我對Quill感到非常失望 - 第一次在使用默認排序類型時,它會生成無效的排序查詢,現在這個。

+0

我修復了我的答案中的錯誤並添加了有關日誌記錄的信息。 – mixel

回答

0

你應該重寫你的查詢:

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))) 
() 
} 

因爲quote必須包含將被編譯成一個單一的查詢表達式。 此代碼將編譯爲三個查詢。

但更好地利用優化的版本:

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))) 
() 
} 

其編譯成兩個查詢。

Quill使用SLF4J進行日誌記錄,您應該閱讀本項目文檔。啓用日誌記錄,你應該添加一些日誌記錄的後端,例如,logback

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

應該爲剛剛記錄的查詢是不夠的。

+0

謝謝,它的工作:)。我可能對Quill的期望過高,也許是因爲我幾年前在ORM方面做了一些工作。但是,奎爾似乎更接近數據庫層,並不像我希望的那樣是傻瓜式的(規則「如果編譯它是正確的」顯然不在這裏,即使使用正確的類型它可能會失敗運行)。 – monnef

+0

其實它似乎是一個錯誤。我報告了它(https://github.com/getquill/quill/issues/974)。 – mixel