Почему я получаю SQLITE_ERROR при использовании SQLite3 с Scala Slick и Joda DateTime?

поэтому я использую удобный помощник joda-mapper отсюда: https://github.com/tototoshi/slick-joda-mapper и при выполнении запроса со сравнением joda DateTime я получаю сообщение об ошибке.

  val today = new DateTime().withTimeAtStartOfDay()
  val yesterday = today.minusDays(1)
val yesterdaysRun = ReportRuns.forReport(report).filter {run => 
  run.runDate >= yesterday && run.runDate < today
}.sortBy(_.runDate.desc).firstOption

Этот код работает нормально, если я опускаю фильтр, но с фильтром я получаю следующую ошибку:

java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (unrecognized token: "{")
    at org.sqlite.DB.newSQLException(DB.java:383)
    at org.sqlite.DB.newSQLException(DB.java:387)
    at org.sqlite.DB.throwex(DB.java:374)
    at org.sqlite.NativeDB.prepare(Native Method)
    at org.sqlite.DB.prepare(DB.java:123)
    at org.sqlite.PrepStmt.<init>(PrepStmt.java:42)
    at org.sqlite.Conn.prepareStatement(Conn.java:404)
    at org.sqlite.Conn.prepareStatement(Conn.java:399)
    at com.mchange.v2.c3p0.impl.NewProxyConnection.prepareStatement(NewProxyConnection.java:275)
    at scala.slick.jdbc.JdbcBackend$SessionDef$class.prepareStatement(JdbcBackend.scala:123)
    at scala.slick.jdbc.JdbcBackend$BaseSession.prepareStatement(JdbcBackend.scala:297)
    at scala.slick.jdbc.StatementInvoker.results(StatementInvoker.scala:28)
    at scala.slick.jdbc.StatementInvoker.iteratorTo(StatementInvoker.scala:16)
    at scala.slick.jdbc.Invoker$class.foreach(Invoker.scala:97)
    at scala.slick.jdbc.StatementInvoker.foreach(StatementInvoker.scala:9)
    at scala.slick.jdbc.Invoker$class.firstOption(Invoker.scala:44)
    at scala.slick.jdbc.StatementInvoker.firstOption(StatementInvoker.scala:9)
    at scala.slick.jdbc.UnitInvoker$class.firstOption(Invoker.scala:155)
    at scala.slick.driver.JdbcInvokerComponent$UnitQueryInvoker.firstOption(JdbcInvokerComponent.scala:50)
    at service.QueryRunnerService$$anonfun$scheduleReports$1$$anonfun$apply$1.apply(QueryRunnerService.scala:57)
...

Мне было интересно, может ли кто-нибудь указать мне правильное направление для решения, возможно, это ошибка экранирования sql в сопоставителе joda? Или что-то еще?

Ниже приведен SQL-запрос, который генерируется (плюс форматирование):

SELECT x2."id", 
       x2."reportid", 
       x2."query", 
       x2."run_date", 
       x2."status", 
       x2."start_time", 
       x2."end_time", 
       x2."error_message", 
       x2."error_details", 
       x2."created_at", 
       x2."updated_at" 
FROM   "report_runs" x2 
WHERE  ( x2."reportid" = 1 ) 
       AND ( ( x2."run_date" >= {ts '2014-03-28 00:00:00.0'} ) 
             AND ( x2."run_date" < {ts '2014-03-29 00:00:00.0'} ) ) 
ORDER  BY x2."run_date" DESC 

person Matthew Rathbone    schedule 28.03.2014    source источник
comment
используйте .selectStatement вместо .firstOption и опубликуйте возвращаемое значение здесь, пожалуйста.   -  person cvogt    schedule 28.03.2014
comment
не знал, что это было даже вещью. Я сделаю это сегодня вечером, когда вернусь домой.   -  person Matthew Rathbone    schedule 28.03.2014
comment
@cvogt Я добавил сгенерированный SQL к вопросу. есть идеи? Разве SQLite не поддерживает отображаемый там синтаксис ts?   -  person Matthew Rathbone    schedule 30.03.2014
comment
это определенно исходит из оболочки joda, которую я использую. например, github.com/tototoshi/slick-joda-mapper/blob/master/src/main/   -  person Matthew Rathbone    schedule 30.03.2014


Ответы (1)


Это ошибка в Joda Mapper (https://github.com/tototoshi/slick-joda-mapper ).

На самом деле в этом картографе много кода, чтобы сделать что-то очень простое. Чтобы обойти эту проблему, лучше всего просто определить простой настраиваемый тип столбца для joda DateTime следующим образом:

    import java.sql.Timestamp
    import org.joda.time.DateTime
    import org.joda.time.DateTimeZone.UTC

    object CustomColumnTypes {
      implicit lazy val jodaType = MappedColumnType.base[DateTime, Timestamp](
         {d => new Timestamp(d.getMillis)} ,
         {d => new DateTime(d.getTime, UTC)}
      )
    }

Обязательно импортируйте соответствующий .simple._ из выбранного вами драйвера.

eg:

import scala.slick.driver.SQLiteDriver.simple._

Для импорта последних версий пакетов slick, scala и joda:

  "org.joda" % "joda-convert" % "2.2.1", // for time convert
  "com.github.tototoshi" %% "slick-joda-mapper" % "2.4.2", // 2.4 doesn't work
  "joda-time" % "joda-time" % "2.7",
  "org.xerial" % "sqlite-jdbc" % "3.30.1", // sqlite driver

Шикарные пакеты:

"com.typesafe.slick" %% "slick" % "3.3.2",
"com.typesafe.slick" %% "slick-codegen" % "3.3.2", // for generating Table schema for sqlite db

Импорт для кода:

import slick.jdbc.SQLiteProfile.api._
Database.forURL(url = absoluteDatabaseUrl)
person Matthew Rathbone    schedule 30.03.2014
comment
Пожалуйста, сообщите об ошибке с ними! - person cvogt; 30.03.2014
comment
Я думаю, это потому, что sqlite-jdbc не поддерживает литералы даты и времени в стиле JDBC. - person tototoshi; 30.03.2014
comment
Я также сообщил об этом как об ошибке в библиотеке. - person Matthew Rathbone; 02.04.2014