Как я могу использовать новый 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 столбцов