From 3b4123f1c0f8fe3484f20d0fe57ba9767f0865b0 Mon Sep 17 00:00:00 2001 From: Minglei Tu Date: Sun, 10 Jul 2016 08:22:29 +0800 Subject: [PATCH] code refactoring for code gen support --- .../tminglei/slickpg/PgArgonautSupport.scala | 23 ++++++----- .../tminglei/slickpg/PgCirceJsonSupport.scala | 32 ++++++++-------- .../tminglei/slickpg/PgDate2Support.scala | 7 ++-- .../tminglei/slickpg/PgDateSupportJoda.scala | 34 ++++++++--------- .../tminglei/slickpg/PgJson4sSupport.scala | 23 ++++++----- .../tminglei/slickpg/PgPostGISSupport.scala | 14 +++++-- .../tminglei/slickpg/PgPlayJsonSupport.scala | 23 ++++++----- .../tminglei/slickpg/PgSprayJsonSupport.scala | 23 ++++++----- .../tminglei/slickpg/PgDateSupport2bp.scala | 7 ++-- .../tminglei/slickpg/ExPostgresProfile.scala | 2 +- .../slickpg/utils/PlainSQLUtils.scala | 2 +- project/Build.scala | 6 +-- .../tminglei/slickpg/PgArraySupport.scala | 38 ++++++++++--------- .../tminglei/slickpg/PgHStoreSupport.scala | 18 +++++---- .../tminglei/slickpg/PgJsonSupport.scala | 22 ++++++----- .../tminglei/slickpg/PgLTreeSupport.scala | 20 ++++++---- .../tminglei/slickpg/PgNetSupport.scala | 21 +++++----- .../tminglei/slickpg/PgRangeSupport.scala | 28 +++++++------- .../tminglei/slickpg/PgSearchSupport.scala | 20 +++++----- 19 files changed, 202 insertions(+), 161 deletions(-) diff --git a/addons/argonaut/src/main/scala/com/github/tminglei/slickpg/PgArgonautSupport.scala b/addons/argonaut/src/main/scala/com/github/tminglei/slickpg/PgArgonautSupport.scala index 32b01f44..65220daa 100644 --- a/addons/argonaut/src/main/scala/com/github/tminglei/slickpg/PgArgonautSupport.scala +++ b/addons/argonaut/src/main/scala/com/github/tminglei/slickpg/PgArgonautSupport.scala @@ -1,17 +1,28 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag trait PgArgonautSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ import argonaut._, Argonaut._ + ///--- def pgjson: String + ///--- + + trait ArgonautCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[Json]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[Json]) + } + } /// alias trait JsonImplicits extends ArgonautJsonImplicits - trait ArgonautJsonImplicits { + trait ArgonautJsonImplicits extends ArgonautCodeGenSupport { implicit val argonautJsonTypeMapper: JdbcType[Json] = new GenericJdbcType[Json]( pgjson, @@ -29,17 +40,9 @@ trait PgArgonautSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTyp } } - trait ArgonautJsonPlainImplicits { + trait ArgonautJsonPlainImplicits extends ArgonautCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[Json]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[Json]) - } - implicit class PgJsonPositionedResult(r: PositionedResult) { def nextJson() = nextJsonOption().getOrElse(jNull) def nextJsonOption() = r.nextStringOption().flatMap(_.parse.toOption) diff --git a/addons/circe-json/src/main/scala/com/github/tminglei/slickpg/PgCirceJsonSupport.scala b/addons/circe-json/src/main/scala/com/github/tminglei/slickpg/PgCirceJsonSupport.scala index c5a9b708..3c6a54bf 100644 --- a/addons/circe-json/src/main/scala/com/github/tminglei/slickpg/PgCirceJsonSupport.scala +++ b/addons/circe-json/src/main/scala/com/github/tminglei/slickpg/PgCirceJsonSupport.scala @@ -1,25 +1,35 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag trait PgCirceJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ import io.circe._ - import io.circe.generic.auto._ import io.circe.parser._ import io.circe.syntax._ + ///--- def pgjson: String + ///--- + + trait CirceCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[Json]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[Json]) + } + } trait JsonImplicits extends CirceImplicits - trait CirceImplicits { + trait CirceImplicits extends CirceCodeGenSupport { implicit val circeJsonTypeMapper: JdbcType[Json] = new GenericJdbcType[Json]( pgjson, - (v) => parse(v).getOrElse(Json.Empty), + (v) => parse(v).getOrElse(Json.Null), (v) => v.asJson.spaces2, - zero = Json.Empty, + zero = Json.Null, hasLiteralForm = false ) @@ -32,20 +42,12 @@ trait PgCirceJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTy } } - trait CirceJsonPlainImplicits { + trait CirceJsonPlainImplicits extends CirceCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[Json]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[Json]) - } - implicit class PgJsonPositionResult(r: PositionedResult) { - def nextJson() = nextJsonOption().getOrElse(Json.Empty) - def nextJsonOption() = r.nextStringOption().map(parse(_).getOrElse(Json.Empty)) + def nextJson() = nextJsonOption().getOrElse(Json.Null) + def nextJsonOption() = r.nextStringOption().map(parse(_).getOrElse(Json.Null)) } implicit val getJson = mkGetResult(_.nextJson()) diff --git a/addons/date2/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala b/addons/date2/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala index 10d0dfa9..e317acfb 100644 --- a/addons/date2/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala +++ b/addons/date2/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala @@ -13,10 +13,11 @@ trait PgDate2Support extends date.PgDateExtensions with utils.PgCommonJdbcTypes import PgDate2SupportUtils._ import driver.api._ - // used to support code gen + // let user to call this, since we have more than one `TIMETZ, DATETIMETZ, INTERVAL` binding candidates here def bindPgDateTypesToScala[DATE, TIME, DATETIME, TIMETZ, DATETIMETZ, INTERVAL]( implicit ctag1: ClassTag[DATE], ctag2: ClassTag[TIME], ctag3: ClassTag[DATETIME], - ctag4: ClassTag[TIMETZ], ctag5: ClassTag[DATETIMETZ], ctag6: ClassTag[INTERVAL]) = { + ctag4: ClassTag[TIMETZ], ctag5: ClassTag[DATETIMETZ], ctag6: ClassTag[INTERVAL]) = { + // register types to let `ExModelBuilder` find them if (driver.isInstanceOf[ExPostgresProfile]) { driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("date", classTag[DATE]) driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("time", classTag[TIME]) @@ -25,7 +26,7 @@ trait PgDate2Support extends date.PgDateExtensions with utils.PgCommonJdbcTypes driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("timestamptz", classTag[DATETIMETZ]) driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("interval", classTag[INTERVAL]) } - else throw new IllegalArgumentException("The driver MUST BE a `ExPostgresDriver`!") + else throw new IllegalArgumentException("The driver MUST BE a `ExPostgresProfile`!") } /// alias diff --git a/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala b/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala index 6042076b..ff4ddac9 100644 --- a/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala +++ b/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala @@ -4,10 +4,22 @@ import org.joda.time._ import org.joda.time.format.{DateTimeFormat, ISODateTimeFormat} import org.postgresql.util.PGInterval import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag trait PgDateSupportJoda extends date.PgDateExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => - import PgJodaSupportUtils._ import driver.api._ + import PgJodaSupportUtils._ + + trait JodaTimeCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("date", classTag[LocalDate]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("time", classTag[LocalTime]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("timestamp", classTag[LocalDateTime]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("timestamptz", classTag[DateTime]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("interval", classTag[Period]) + } + } /// alias trait DateTimeImplicits extends JodaDateTimeImplicits @@ -24,7 +36,7 @@ trait PgDateSupportJoda extends date.PgDateExtensions with utils.PgCommonJdbcTyp val jodaTzDateTimeFormatter_NoFraction = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ssZ") } - trait JodaDateTimeImplicits extends JodaDateTimeFormatters { + trait JodaDateTimeImplicits extends JodaDateTimeFormatters with JodaTimeCodeGenSupport { implicit val jodaDateTypeMapper: JdbcType[LocalDate] = new GenericJdbcType[LocalDate]("date", LocalDate.parse(_, jodaDateFormatter), _.toString(jodaDateFormatter), hasLiteralForm=false) implicit val jodaTimeTypeMapper: JdbcType[LocalTime] = new GenericJdbcType[LocalTime]("time", @@ -71,24 +83,10 @@ trait PgDateSupportJoda extends date.PgDateExtensions with utils.PgCommonJdbcTyp new TimestampColumnExtensionMethods[LocalDate, LocalTime, DateTime, LocalDateTime, Period, Option[DateTime]](c) } - trait JodaDateTimePlainImplicits extends JodaDateTimeFormatters { + trait JodaDateTimePlainImplicits extends JodaDateTimeFormatters with JodaTimeCodeGenSupport { import java.sql.Types - import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("date", classTag[LocalDate]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("time", classTag[LocalTime]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("timestamp", classTag[LocalDateTime]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("timestamptz", classTag[DateTime]) - // let users do it by themselves -// driver.asInstanceOf[ExPostgresDriver].bindPgTypeToScala("interval", classTag[Duration]) -// driver.asInstanceOf[ExPostgresDriver].bindPgTypeToScala("interval", classTag[Period]) - } - implicit class PgDate2TimePositionedResult(r: PositionedResult) { def nextLocalDate() = nextLocalDateOption().orNull def nextLocalDateOption() = r.nextStringOption().map(LocalDate.parse(_, jodaDateFormatter)) @@ -137,7 +135,7 @@ trait PgDateSupportJoda extends date.PgDateExtensions with utils.PgCommonJdbcTyp } object PgJodaSupportUtils { - /// pg interval string --> joda Duration + /// pg interval string --> joda Period def pgIntervalStr2jodaPeriod(intervalStr: String): Period = { val pgInterval = new PGInterval(intervalStr) val seconds = Math.floor(pgInterval.getSeconds) .asInstanceOf[Int] diff --git a/addons/json4s/src/main/scala/com/github/tminglei/slickpg/PgJson4sSupport.scala b/addons/json4s/src/main/scala/com/github/tminglei/slickpg/PgJson4sSupport.scala index 661e7b76..14c2fbb8 100644 --- a/addons/json4s/src/main/scala/com/github/tminglei/slickpg/PgJson4sSupport.scala +++ b/addons/json4s/src/main/scala/com/github/tminglei/slickpg/PgJson4sSupport.scala @@ -1,20 +1,31 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag trait PgJson4sSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ import org.json4s._ + ///--- type DOCType def pgjson: String val jsonMethods: JsonMethods[DOCType] + ///--- + + trait Json4sCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JValue]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JValue]) + } + } /// alias trait JsonImplicits extends Json4sJsonImplicits - trait Json4sJsonImplicits { + trait Json4sJsonImplicits extends Json4sCodeGenSupport { implicit val json4sJsonTypeMapper: JdbcType[JValue] = new GenericJdbcType[JValue]( pgjson, @@ -32,17 +43,9 @@ trait PgJson4sSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes } } - trait Json4sJsonPlainImplicits { + trait Json4sJsonPlainImplicits extends Json4sCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JValue]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JValue]) - } - implicit class PgJsonPositionedResult(r: PositionedResult) { def nextJson() = nextJsonOption().getOrElse(JNull) def nextJsonOption() = r.nextStringOption().map(jsonMethods.parse(_)) diff --git a/addons/jts/src/main/scala/com/github/tminglei/slickpg/PgPostGISSupport.scala b/addons/jts/src/main/scala/com/github/tminglei/slickpg/PgPostGISSupport.scala index c78c11b1..50a04045 100644 --- a/addons/jts/src/main/scala/com/github/tminglei/slickpg/PgPostGISSupport.scala +++ b/addons/jts/src/main/scala/com/github/tminglei/slickpg/PgPostGISSupport.scala @@ -7,14 +7,22 @@ import com.vividsolutions.jts.io.{WKBReader, WKBWriter, WKTReader, WKTWriter} import slick.ast.FieldSymbol import slick.jdbc._ -import scala.reflect.ClassTag +import scala.reflect.{classTag, ClassTag} trait PgPostGISSupport extends geom.PgPostGISExtensions { driver: PostgresProfile => import driver.api._ + trait PostGISCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("geometry", classTag[Geometry]) + } + } + + /// trait PostGISAssistants extends BasePostGISAssistants[Geometry, Point, LineString, Polygon, GeometryCollection] - trait PostGISImplicits { + trait PostGISImplicits extends PostGISCodeGenSupport { implicit val geometryTypeMapper: JdbcType[Geometry] = new GeometryJdbcType[Geometry] implicit val pointTypeMapper: JdbcType[Point] = new GeometryJdbcType[Point] implicit val polygonTypeMapper: JdbcType[Polygon] = new GeometryJdbcType[Polygon] @@ -32,7 +40,7 @@ trait PgPostGISSupport extends geom.PgPostGISExtensions { driver: PostgresProfil new GeometryColumnExtensionMethods[Geometry, Point, LineString, Polygon, GeometryCollection, G1, Option[G1]](c) } - trait PostGISPlainImplicits { + trait PostGISPlainImplicits extends PostGISCodeGenSupport { import PgPostGISSupportUtils._ import utils.PlainSQLUtils._ diff --git a/addons/play-json/src/main/scala/com/github/tminglei/slickpg/PgPlayJsonSupport.scala b/addons/play-json/src/main/scala/com/github/tminglei/slickpg/PgPlayJsonSupport.scala index 52971629..04113999 100644 --- a/addons/play-json/src/main/scala/com/github/tminglei/slickpg/PgPlayJsonSupport.scala +++ b/addons/play-json/src/main/scala/com/github/tminglei/slickpg/PgPlayJsonSupport.scala @@ -1,17 +1,28 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag trait PgPlayJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ import play.api.libs.json._ + ///--- def pgjson: String + ///--- + + trait PlayJsonCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JsValue]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JsValue]) + } + } /// alias trait JsonImplicits extends PlayJsonImplicits - trait PlayJsonImplicits { + trait PlayJsonImplicits extends PlayJsonCodeGenSupport { implicit val playJsonTypeMapper: JdbcType[JsValue] = new GenericJdbcType[JsValue]( pgjson, @@ -29,17 +40,9 @@ trait PgPlayJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTyp } } - trait PlayJsonPlainImplicits { + trait PlayJsonPlainImplicits extends PlayJsonCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JsValue]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JsValue]) - } - implicit class PgJsonPositionedResult(r: PositionedResult) { def nextJson() = nextJsonOption().getOrElse(JsNull) def nextJsonOption() = r.nextStringOption().map(Json.parse) diff --git a/addons/spray-json/src/main/scala/com/github/tminglei/slickpg/PgSprayJsonSupport.scala b/addons/spray-json/src/main/scala/com/github/tminglei/slickpg/PgSprayJsonSupport.scala index 8753bb6e..27cd737e 100644 --- a/addons/spray-json/src/main/scala/com/github/tminglei/slickpg/PgSprayJsonSupport.scala +++ b/addons/spray-json/src/main/scala/com/github/tminglei/slickpg/PgSprayJsonSupport.scala @@ -1,18 +1,29 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag trait PgSprayJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ import spray.json._ import DefaultJsonProtocol._ // !!! IMPORTANT, otherwise `convertTo` and `toJson` won't work correctly. + ///--- def pgjson: String + ///--- + + trait SprayJsonCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JsValue]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JsValue]) + } + } /// alias trait JsonImplicits extends SprayJsonImplicits - trait SprayJsonImplicits { + trait SprayJsonImplicits extends SprayJsonCodeGenSupport { implicit val sprayJsonTypeMapper: JdbcType[JsValue] = new GenericJdbcType[JsValue]( pgjson, @@ -30,17 +41,9 @@ trait PgSprayJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTy } } - trait SprayJsonPlainImplicits { + trait SprayJsonPlainImplicits extends SprayJsonCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JsValue]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JsValue]) - } - implicit class PgJsonPositionedResult(r: PositionedResult) { def nextJson() = nextJsonOption().getOrElse(JsNull) def nextJsonOption() = r.nextStringOption().map(_.parseJson) diff --git a/addons/threeten/src/main/scala/com/github/tminglei/slickpg/PgDateSupport2bp.scala b/addons/threeten/src/main/scala/com/github/tminglei/slickpg/PgDateSupport2bp.scala index a683ac43..6961e391 100644 --- a/addons/threeten/src/main/scala/com/github/tminglei/slickpg/PgDateSupport2bp.scala +++ b/addons/threeten/src/main/scala/com/github/tminglei/slickpg/PgDateSupport2bp.scala @@ -12,10 +12,11 @@ trait PgDateSupport2bp extends date.PgDateExtensions with utils.PgCommonJdbcType import PgThreetenSupportUtils._ import driver.api._ - // used to support code gen + // let user to call this, since we have more than one `TIMETZ, DATETIMETZ, INTERVAL` binding candidates here def bindPgDateTypesToScala[DATE, TIME, DATETIME, TIMETZ, DATETIMETZ, INTERVAL]( implicit ctag1: ClassTag[DATE], ctag2: ClassTag[TIME], ctag3: ClassTag[DATETIME], - ctag4: ClassTag[TIMETZ], ctag5: ClassTag[DATETIMETZ], ctag6: ClassTag[INTERVAL]) = { + ctag4: ClassTag[TIMETZ], ctag5: ClassTag[DATETIMETZ], ctag6: ClassTag[INTERVAL]) = { + // register types to let `ExModelBuilder` find them if (driver.isInstanceOf[ExPostgresProfile]) { driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("date", classTag[DATE]) driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("time", classTag[TIME]) @@ -24,7 +25,7 @@ trait PgDateSupport2bp extends date.PgDateExtensions with utils.PgCommonJdbcType driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("timestamptz", classTag[DATETIMETZ]) driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("interval", classTag[INTERVAL]) } - else throw new IllegalArgumentException("The driver MUST BE a `ExPostgresDriver`!") + else throw new IllegalArgumentException("The driver MUST BE a `ExPostgresProfile`!") } /// alias diff --git a/core/src/main/scala/com/github/tminglei/slickpg/ExPostgresProfile.scala b/core/src/main/scala/com/github/tminglei/slickpg/ExPostgresProfile.scala index a1f9782c..6de108e9 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/ExPostgresProfile.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/ExPostgresProfile.scala @@ -125,7 +125,7 @@ trait ExPostgresProfile extends JdbcProfile with PostgresProfile with Logging { pgTypeToScala.synchronized { val existed = pgTypeToScala.get(pgType) if (existed.isDefined) logger.warn( - s"\u001B[31m >>> DUPLICATED BINDING - existed: ${existed.get}, new: $scalaType !!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" + s"\u001B[31m >>> DUPLICATED binding for $pgType - existed: ${existed.get}, new: $scalaType !!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" ) pgTypeToScala += (pgType -> scalaType) } diff --git a/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala b/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala index fb7ef0ac..46d98e1a 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala @@ -18,7 +18,7 @@ object PlainSQLUtils extends Logging { val convKey = u.typeOf[T].toString val existed = nextArrayConverters.get(convKey) if (existed.isDefined) logger.warn( - s"\u001B[31m >>> DUPLICATED converter for ${u.typeOf[T]}!!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" + s"\u001B[31m >>> DUPLICATED next array converter for ${u.typeOf[T]}!!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" ) nextArrayConverters += (convKey -> conv) } diff --git a/project/Build.scala b/project/Build.scala index 946e6a94..87f54928 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -149,9 +149,9 @@ object SlickPgBuild extends Build { name := "slick-pg_circe-json", description := "Slick extensions for PostgreSQL - circe module", libraryDependencies := mainDependencies(scalaVersion.value) ++ Seq( - "io.circe" %% "circe-core" % "0.3.0", - "io.circe" %% "circe-generic" % "0.3.0", - "io.circe" %% "circe-parser" % "0.3.0" + "io.circe" %% "circe-core" % "0.4.1", + "io.circe" %% "circe-generic" % "0.4.1", + "io.circe" %% "circe-parser" % "0.4.1" ) ) ) dependsOn (slickPgCore) diff --git a/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala index 12dc2936..73d9148b 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala @@ -4,14 +4,32 @@ import java.util.UUID import java.sql.{Date, Time, Timestamp} import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} import scala.reflect.runtime.{universe => u} +import scala.reflect.classTag trait PgArraySupport extends array.PgArrayExtensions with array.PgArrayJdbcTypes { driver: PostgresProfile => import driver.api._ + trait SimpleArrayCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_uuid", classTag[Seq[UUID]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_text", classTag[Seq[String]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_int8", classTag[Seq[Long]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_int4", classTag[Seq[Int]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_int2", classTag[Seq[Short]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_float4", classTag[Seq[Float]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_float8", classTag[Seq[Double]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_bool", classTag[Seq[Boolean]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_date", classTag[Seq[Date]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_time", classTag[Seq[Time]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_timestamp", classTag[Seq[Timestamp]]) + } + } + /// alias trait ArrayImplicits extends SimpleArrayImplicits - trait SimpleArrayImplicits { + trait SimpleArrayImplicits extends SimpleArrayCodeGenSupport { /** for type/name, @see [[org.postgresql.core.Oid]] and [[org.postgresql.jdbc2.TypeInfoCache]]*/ implicit val simpleUUIDListTypeMapper: JdbcType[List[UUID]] = new SimpleArrayJdbcType[UUID]("uuid").to(_.toList) implicit val simpleStrListTypeMapper: JdbcType[List[String]] = new SimpleArrayJdbcType[String]("text").to(_.toList) @@ -37,29 +55,13 @@ trait PgArraySupport extends array.PgArrayExtensions with array.PgArrayJdbcTypes } /// static sql support, NOTE: no extension methods available for static sql usage - trait SimpleArrayPlainImplicits { - import scala.reflect.classTag + trait SimpleArrayPlainImplicits extends SimpleArrayCodeGenSupport { import utils.PlainSQLUtils._ // to support 'nextArray[T]/nextArrayOption[T]' in PgArraySupport { addNextArrayConverter((r) => simpleNextArray[Int](r).map(_.map(_.toShort))) } - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_uuid", classTag[Seq[UUID]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_text", classTag[Seq[String]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_int8", classTag[Seq[Long]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_int4", classTag[Seq[Int]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_int2", classTag[Seq[Short]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_float4", classTag[Seq[Float]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_float8", classTag[Seq[Double]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_bool", classTag[Seq[Boolean]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_date", classTag[Seq[Date]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_time", classTag[Seq[Time]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_timestamp", classTag[Seq[Timestamp]]) - } - implicit class PgArrayPositionedResult(r: PositionedResult) { def nextArray[T]()(implicit tpe: u.TypeTag[T]): Seq[T] = nextArrayOption[T]().getOrElse(Nil) def nextArrayOption[T]()(implicit ttag: u.TypeTag[T]): Option[Seq[T]] = { diff --git a/src/main/scala/com/github/tminglei/slickpg/PgHStoreSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgHStoreSupport.scala index 218314bc..9fa843e0 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgHStoreSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgHStoreSupport.scala @@ -3,14 +3,22 @@ package com.github.tminglei.slickpg import scala.collection.convert.{WrapAsJava, WrapAsScala} import org.postgresql.util.HStoreConverter import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag trait PgHStoreSupport extends hstore.PgHStoreExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ + trait HStoreCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("hstore", classTag[Map[String, String]]) + } + } + /// alias trait HStoreImplicits extends SimpleHStoreImplicits - trait SimpleHStoreImplicits { + trait SimpleHStoreImplicits extends HStoreCodeGenSupport { implicit val simpleHStoreTypeMapper: JdbcType[Map[String, String]] = new GenericJdbcType[Map[String, String]]( "hstore", @@ -28,14 +36,8 @@ trait PgHStoreSupport extends hstore.PgHStoreExtensions with utils.PgCommonJdbcT } /// static sql support, NOTE: no extension methods available for static sql usage - trait SimpleHStorePlainImplicits { + trait SimpleHStorePlainImplicits extends HStoreCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("hstore", classTag[Map[String, String]]) - } implicit class PgHStorePositionedResult(r: PositionedResult) { def nextHStore() = nextHStoreOption().getOrElse(Map.empty) diff --git a/src/main/scala/com/github/tminglei/slickpg/PgJsonSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgJsonSupport.scala index 8784d137..1162e0ba 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgJsonSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgJsonSupport.scala @@ -1,6 +1,7 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag /** simple json string wrapper */ case class JsonString(value: String) @@ -11,12 +12,22 @@ case class JsonString(value: String) trait PgJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ + ///--- def pgjson: String + ///--- + + trait SimpleJsonCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JsonString]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JsonString]) + } + } /// alias trait JsonImplicits extends SimpleJsonImplicits - trait SimpleJsonImplicits { + trait SimpleJsonImplicits extends SimpleJsonCodeGenSupport { implicit val simpleJsonTypeMapper: JdbcType[JsonString] = new GenericJdbcType[JsonString]( pgjson, @@ -33,15 +44,8 @@ trait PgJsonSupport extends json.PgJsonExtensions with utils.PgCommonJdbcTypes { } } - trait SimpleJsonPlainImplicits { + trait SimpleJsonPlainImplicits extends SimpleJsonCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("json", classTag[JsonString]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("jsonb", classTag[JsonString]) - } implicit class PgJsonPositionedResult(r: PositionedResult) { def nextJson() = nextJsonOption().orNull diff --git a/src/main/scala/com/github/tminglei/slickpg/PgLTreeSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgLTreeSupport.scala index 9ea6681b..1bf2b4a7 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgLTreeSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgLTreeSupport.scala @@ -1,6 +1,7 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag /** simple ltree wrapper */ case class LTree(value: List[String]) { @@ -17,10 +18,18 @@ object LTree { trait PgLTreeSupport extends ltree.PgLTreeExtensions with utils.PgCommonJdbcTypes with array.PgArrayJdbcTypes { driver: PostgresProfile => import driver.api._ + trait SimpleLTreeCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("ltree", classTag[LTree]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("_ltree", classTag[List[LTree]]) + } + } + /// alias trait LTreeImplicits extends SimpleLTreeImplicits - trait SimpleLTreeImplicits { + trait SimpleLTreeImplicits extends SimpleLTreeCodeGenSupport { implicit val simpleLTreeTypeMapper: JdbcType[LTree] = new GenericJdbcType[LTree]("ltree", (v) => LTree(v), @@ -48,19 +57,14 @@ trait PgLTreeSupport extends ltree.PgLTreeExtensions with utils.PgCommonJdbcType } } - trait SimpleLTreePlainImplicits { - import scala.reflect.classTag + trait SimpleLTreePlainImplicits extends SimpleLTreeCodeGenSupport { import utils.PlainSQLUtils._ + // to support 'nextArray[T]/nextArrayOption[T]' in PgArraySupport { addNextArrayConverter((r) => utils.SimpleArrayUtils.fromString(LTree.apply)(r.nextString())) } - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("ltree", classTag[LTree]) - } - implicit class PgLTreePositionedResult(r: PositionedResult) { def nextLTree() = nextLTreeOption().orNull def nextLTreeOption() = r.nextStringOption().map(LTree.apply) diff --git a/src/main/scala/com/github/tminglei/slickpg/PgNetSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgNetSupport.scala index 48d90243..e112ee94 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgNetSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgNetSupport.scala @@ -1,6 +1,7 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag /** simple inet string wrapper */ case class InetString(value: String) { @@ -23,10 +24,18 @@ case class MacAddrString(value: String) trait PgNetSupport extends net.PgNetExtensions with utils.PgCommonJdbcTypes { driver: PostgresProfile => import driver.api._ + trait SimpleNetCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("inet", classTag[InetString]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("macaddr", classTag[MacAddrString]) + } + } + /// alias trait NetImplicits extends SimpleNetImplicits - trait SimpleNetImplicits { + trait SimpleNetImplicits extends SimpleNetCodeGenSupport { implicit val simpleInetTypeMapper: JdbcType[InetString] = new GenericJdbcType[InetString]("inet", (v) => InetString(v), @@ -55,21 +64,15 @@ trait PgNetSupport extends net.PgNetExtensions with utils.PgCommonJdbcTypes { dr } } - trait SimpleNetPlainImplicits { - import scala.reflect.classTag + trait SimpleNetPlainImplicits extends SimpleNetCodeGenSupport { import utils.PlainSQLUtils._ + // to support 'nextArray[T]/nextArrayOption[T]' in PgArraySupport { addNextArrayConverter((r) => utils.SimpleArrayUtils.fromString(InetString.apply)(r.nextString())) addNextArrayConverter((r) => utils.SimpleArrayUtils.fromString(MacAddrString.apply)(r.nextString())) } - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("inet", classTag[InetString]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("macaddr", classTag[MacAddrString]) - } - implicit class PgNetPositionedResult(r: PositionedResult) { def nextIPAddr() = nextIPAddrOption().orNull def nextIPAddrOption() = r.nextStringOption().map(InetString) diff --git a/src/main/scala/com/github/tminglei/slickpg/PgRangeSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgRangeSupport.scala index 5edbbe28..35409e49 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgRangeSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgRangeSupport.scala @@ -1,8 +1,8 @@ package com.github.tminglei.slickpg import java.sql.{Date, Timestamp} - import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag // edge type definitions sealed trait EdgeType @@ -45,10 +45,21 @@ trait PgRangeSupport extends range.PgRangeExtensions with utils.PgCommonJdbcType private def toTimestamp(str: String) = Timestamp.valueOf(str) private def toSQLDate(str: String) = Date.valueOf(str) + trait SimpleRangeCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("int4range", classTag[Range[Int]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("int8range", classTag[Range[Long]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("numrange", classTag[Range[Float]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("tsrange", classTag[Range[Timestamp]]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("daterange", classTag[Range[Date]]) + } + } + /// alias trait RangeImplicits extends SimpleRangeImplicits - trait SimpleRangeImplicits { + trait SimpleRangeImplicits extends SimpleRangeCodeGenSupport { implicit val simpleIntRangeTypeMapper: JdbcType[Range[Int]] = new GenericJdbcType[Range[Int]]("int4range", mkRangeFn(_.toInt)) implicit val simpleLongRangeTypeMapper: JdbcType[Range[Long]] = new GenericJdbcType[Range[Long]]("int8range", mkRangeFn(_.toLong)) implicit val simpleFloatRangeTypeMapper: JdbcType[Range[Float]] = new GenericJdbcType[Range[Float]]("numrange", mkRangeFn(_.toFloat)) @@ -65,9 +76,9 @@ trait PgRangeSupport extends range.PgRangeExtensions with utils.PgCommonJdbcType } } - trait SimpleRangePlainImplicits { - import scala.reflect.classTag + trait SimpleRangePlainImplicits extends SimpleRangeCodeGenSupport { import utils.PlainSQLUtils._ + // to support 'nextArray[T]/nextArrayOption[T]' in PgArraySupport { addNextArrayConverter((r) => utils.SimpleArrayUtils.fromString(mkRangeFn(_.toInt))(r.nextString())) @@ -77,15 +88,6 @@ trait PgRangeSupport extends range.PgRangeExtensions with utils.PgCommonJdbcType addNextArrayConverter((r) => utils.SimpleArrayUtils.fromString(mkRangeFn(toSQLDate))(r.nextString())) } - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("int4range", classTag[Range[Int]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("int8range", classTag[Range[Long]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("numrange", classTag[Range[Float]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("tsrange", classTag[Range[Timestamp]]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("daterange", classTag[Range[Date]]) - } - implicit class PgRangePositionedResult(r: PositionedResult) { def nextIntRange() = nextIntRangeOption().orNull def nextIntRangeOption() = r.nextStringOption().map(mkRangeFn(_.toInt)) diff --git a/src/main/scala/com/github/tminglei/slickpg/PgSearchSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgSearchSupport.scala index 64fff36a..b343b521 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgSearchSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgSearchSupport.scala @@ -1,6 +1,7 @@ package com.github.tminglei.slickpg import slick.jdbc.{JdbcType, PositionedResult, PostgresProfile} +import scala.reflect.classTag /** simple tsvector/tsquery string wrapper */ case class TsVector(value: String) @@ -11,10 +12,18 @@ trait PgSearchSupport extends search.PgSearchExtensions with utils.PgCommonJdbcT trait SearchAssistants extends BaseSearchAssistants[TsVector, TsQuery] + trait SearchCodeGenSupport { + // register types to let `ExModelBuilder` find them + if (driver.isInstanceOf[ExPostgresProfile]) { + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("tsvector", classTag[TsVector]) + driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("tsquery", classTag[TsQuery]) + } + } + /// alias trait SearchImplicits extends SimpleSearchImplicits - trait SimpleSearchImplicits { + trait SimpleSearchImplicits extends SearchCodeGenSupport { implicit val simpleTsVectorTypeMapper: JdbcType[TsVector] = new GenericJdbcType[TsVector]("tsvector", TsVector, _.value) implicit val simpleTsQueryTypeMapper: JdbcType[TsQuery] = new GenericJdbcType[TsQuery]("tsquery", TsQuery, _.value) @@ -32,15 +41,8 @@ trait PgSearchSupport extends search.PgSearchExtensions with utils.PgCommonJdbcT } } - trait SimpleSearchPlainImplicits { + trait SimpleSearchPlainImplicits extends SearchCodeGenSupport { import utils.PlainSQLUtils._ - import scala.reflect.classTag - - // used to support code gen - if (driver.isInstanceOf[ExPostgresProfile]) { - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("tsvector", classTag[TsVector]) - driver.asInstanceOf[ExPostgresProfile].bindPgTypeToScala("tsquery", classTag[TsQuery]) - } implicit class PgSearchPositionedResult(r: PositionedResult) { def nextTsVector() = nextTsVectorOption().orNull