Как я могу использовать новый Slick 2.0 HList, чтобы преодолеть ограничение в 22 столбца?

В настоящее время я пишу код Slick для целевой старой схемы с двумя таблицами> 22 столбцов. Как мне использовать новый код HList? У меня 2.0-M3 работает нормально в Scala 2.10.3. Вот синтаксис, который я сейчас использую с case-классами / кортежами. Что бы я сделал, чтобы использовать новые списки HL, упомянутые в документах?

  case class Joiner(
      id: Int,
      name: Option[String],
      contact: Option[String]
  )

  class Joiners(tag: Tag) extends Table[Joiner](tag, "joiner") {
    def id = column[Int]("id", O.PrimaryKey, O.AutoInc, O.DBType("int(11)"))
    def name = column[Option[String]]("name", O.DBType("varchar(255)"))
    def contact = column[Option[String]]("contact", O.DBType("text"))
    def * = (id, name.?, contact.?) <> (Joiner.tupled, Joiner.unapply)
  }
  val joiners = TableQuery[Joiners]

Я не вижу ничего в примерах и только краткое упоминание в недавно обновленных документах. Я новичок в Scala, а также Slick.

2 ответа

Решение

Определение

С Scala >= 2.10.4-RC2 (также генерируется генератором кода Slick 2.0.0):

import scala.slick.collection.heterogenous._
import syntax._
class Joiners(tag: Tag) extends Table[
    Int :: Option[String] :: Option[String] :: HNil
](tag, "joiner") {
  ...
  def * = id :: name :: contact :: HNil
}

Выше приведено время экспоненциальной компиляции в Scala 2.10.3 / 2.10.4-RC1. Не возможно для более чем 26 столбцов из-за очень долгой компиляции.

Обходной путь для Scala <= 2.10.3 / 2.10.4-RC1 (также генерируется генератором кода Slick 2.0.1)

import scala.slick.collection.heterogenous._
import syntax._
class Joiners(tag: Tag) extends Table[
    HCons[Int, HCons[Option[String], HCons[Option[String], HNil]]]
](tag, "joiner") {
  ...
  def * = id :: name :: contact :: HNil
}

Протестировано нами с 30-40 колонками без проблем.

В настоящее время, похоже, все еще существует проблема со случайными спорадическими ошибками компиляции в Scala 2.10.4-RC2, которая, похоже, будет исправлена ​​в следующей 2.10.4-RC3. См. https://issues.scala-lang.org/browse/SI-8146

Пример использования

Joiners.run.map( r => r(2) ) // Gets column contact. It's typesafe. .apply is a macro. Only works for literals not for variables as positions.

Используйте кортежи для < 22, чтобы иметь возможность сопоставить их с классом дел. Используйте HLists для> 22 без сопоставления с классом дел (максимальный предел поля в Scala 2.10 равен 22).

Также: НЕ используйте O.Nullable. использование column[Option[String]] вместо. Это подразумевает обнуляемость.

Этот код демонстрирует проблему с производительностью, все еще влияющую на компилятор (он просто застревает) в Scala v2.10.4_RC1, когда число столбцов превышает 26

import java.sql.Timestamp
import scala.slick.driver.MySQLDriver.simple._
import scala.slick.collection.heterogenous._
// **** Uncomment this ****
//import scala.slick.collection.heterogenous.syntax._  



object DealSlick {


    class Deals(tag: Tag) extends Table[
      Long :: String :: String :: Option[String] :: Option[String] :: Option[String] ::
      // urlKeywords
      Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
      // extTags
      Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] :: 
      // currency
      Option[String] :: Option[String] :: 
      // price
      Option[Double] :: Option[Double] :: Option[Double] :: Option[Double] ::
      // extStatus
      Option[String] :: Option[String] :: Option[Int] :: Option[Int] ::

     /* If you add more columns the compiler get stuck in a never-ending
      * compilation possibly related to 
      * https://github.com/slick/slick/issues/577
      */

     // endAt
     Option[Timestamp] :: /*Option[Timestamp] :: Option[Timestamp] :: Option[Timestamp] ::
     // timeZoneOffset
     Option[Int] :: Option[String] :: Option[Timestamp] :: Option[String] ::
     // locationName
     Option[String] :: Option[String] :: Option[String] :: Option[String] ::
     // city
     Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] :: 
     // latitude
     Option[Double] :: Option[Double] :: 
     // merchantTitle
     Option[String] :: */
     // End of list
     HNil
     ](tag, "deal") {
     def                id = column[Long]("id", O.PrimaryKey)
     def          siteName = column[String]("partner_site_name", O.NotNull)
     def        siteDomain = column[String]("partner_site_domain", O.NotNull)
     def    localeLanguage = column[Option[String]]("deal_language") 
     def     localeCountry = column[Option[String]]("deal_country") 
     def             extId = column[Option[String]]("deal_ext_id") 
     def       urlKeywords = column[Option[String]]("deal_url_keywords") 
     def          keywords = column[Option[String]]("deal_keywords") 
     def     extCategories = column[Option[String]]("deal_ext_categories") 
     def      categoryText = column[Option[String]]("deal_category_text") 
     def          coverage = column[Option[String]]("deal_coverage") 
     def           extTags = column[Option[String]]("deal_ext_tags") 
     def             title = column[Option[String]]("deal_title") 
     def       description = column[Option[String]]("deal_description")
     def          extImage = column[Option[String]]("deal_ext_image") 
     def               url = column[Option[String]]("deal_url") 
     def          currency = column[Option[String]]("deal_currency") 
     def       currencySym = column[Option[String]]("deal_currency_sym") 
     def             price = column[Option[Double]]("deal_price") 
     def            saving = column[Option[Double]]("deal_saving") 
     def          discount = column[Option[Double]]("deal_discount") 
     def            dvalue = column[Option[Double]]("deal_value") 
     def         extStatus = column[Option[String]]("deal_ext_status") 
     def            status = column[Option[String]]("deal_status") 
     def           soldQty = column[Option[Int]]("deal_sold_qty") 
     def           leftQty = column[Option[Int]]("deal_left_qty") 
     def             endAt = column[Option[Timestamp]]("deal_end_at") 
 /*    def          endAtUtc = column[Option[Timestamp]]("deal_end_at_utc") 
     def         expiresAt = column[Option[Timestamp]]("deal_expires_at") 
     def      expiresAtUtc = column[Option[Timestamp]]("deal_expires_at_utc") 
     def    timeZoneOffset = column[Option[Int]]("time_zone_offset") 
     def      timeZoneName = column[Option[String]]("time_zone_name")
     def       timeGrabbed = column[Option[Timestamp]]("time_grabbed") 
     def  timeRemainingStr = column[Option[String]]("time_remaining_str") 
     def      locationName = column[Option[String]]("location_name")
     def           address = column[Option[String]]("location_address") 
     def            street = column[Option[String]]("location_street") 
     def        postalCode = column[Option[String]]("location_postalcode")
     def              city = column[Option[String]]("location_city") 
     def          province = column[Option[String]]("location_province") 
     def            region = column[Option[String]]("location_region") 
     def             state = column[Option[String]]("location_state") 
     def           country = column[Option[String]]("location_country") 
     def          latitude = column[Option[Double]]("location_latitude") 
     def         longitude = column[Option[Double]]("location_longitude") 
     def     merchantTitle = column[Option[String]]("merchant_title") 

*/
def * = (id :: siteName :: siteDomain :: localeLanguage :: localeCountry :: extId :: 
         urlKeywords :: keywords :: extCategories :: categoryText :: coverage :: 
         extTags :: title :: description :: extImage :: url ::
         currency :: currencySym :: price :: saving :: discount :: dvalue ::
         extStatus :: status :: soldQty :: leftQty ::
         endAt :: /*endAtUtc :: expiresAt :: expiresAtUtc ::
         timeZoneOffset :: timeZoneName :: timeGrabbed :: timeRemainingStr ::
         locationName :: address :: street :: postalCode :: 
         city :: province :: region :: state :: country ::
         latitude :: longitude ::
         merchantTitle :: */
         HNil )  
   }

}

** ОБНОВИТЬ **

После обновления до Scala 2.10.4-RC2, компилятор делает несколько шагов дальше в процессе компиляции, но снова застревает:

Вот вывод компилятора при определении только нескольких столбцов таблицы

[info] [загруженный файл класса /Users/max/.ivy2/cache/com.typesafe.slick/slick_2.10/jars/slick_2.10-2.0.0.jar(scala/slick/backend/DatabaseComponent.class) в 1мс]

[info] [загруженный файл класса /Users/max/.ivy2/cache/com.typesafe.slick/slick_2.10/jars/slick_2.10-2.0.0.jar(scala/slick/lifted/ShapedValue.class) в 2мс]

[info] [загруженный загрузчик пакетов через 2 мс] Этот вывод никогда не выводится на экран при использовании более 26 столбцов

Другие вопросы по тегам