Skip to content

Commit

Permalink
postgres - doobie:
Browse files Browse the repository at this point in the history
uuid/json/enum
  • Loading branch information
djnzx committed Sep 7, 2023
1 parent acdf6d1 commit 338e7ab
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ maxColumn = 140
trailingCommas=preserve
align {
preset = most // better indentation inside for
tokens = ["%", "%%", "=>", "=", "->", "<-", "//"]
tokens = ["%", "%%", "=>", "=", "->", "<-", "//", "extends"]
// openParenCallSite = false
// openParenDefnSite = false
}
Expand Down
2 changes: 1 addition & 1 deletion ce3/src/main/scala/doobiex/Db.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ object Db {
private val env = sys.env

val driver = "org.postgresql.Driver"
val url = env.getOrElse("JDBC_URL", "jdbc:postgresql://localhost:5432/se2")
val url = env.getOrElse("JDBC_URL", "jdbc:postgresql://localhost:5432/fs1")
val user = env.getOrElse("JDBC_USER", "postgres")
val pass = env.getOrElse("JDBC_PASSWORD", "pg123456")
}
51 changes: 0 additions & 51 deletions ce3/src/main/scala/doobiex/Doobie4.scala

This file was deleted.

39 changes: 39 additions & 0 deletions ce3/src/main/scala/doobiex/enums/EnumMappingApp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package doobiex.enums

import cats.effect._
import cats.implicits._
import doobie._
import doobie.implicits._
import doobiex.xa
import java.util.UUID

/** Postgres ENUM internal implementation
* syntax:
* {{{
* create type message_type AS ENUM('trace', 'debug', 'info', 'warn', 'error', 'fatal')
* }}}
* motivation:
* - internal state just 4-byte integer
* - ordering works out of the box
*/
object EnumMappingApp extends IOApp.Simple {

/** required to derive Get[MyRow]
* import MetaInstances._
*/

import doobiex.uuid.InstancesUuidMeta._

case class MyRow(id: UUID, typ: MessageType, msg: String)

val program: ConnectionIO[List[MyRow]] = sql"select id, typ, msg from messages"
.query[MyRow]
.to[List]

val io: IO[List[MyRow]] = program.transact(xa[IO])

override def run: IO[Unit] =
program
.transact(xa[IO])
.flatMap(_.traverse_(x => IO(pprint.pprintln(x))))
}
18 changes: 18 additions & 0 deletions ce3/src/main/scala/doobiex/enums/MessageType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package doobiex.enums

import enumeratum._
import enumeratum.EnumEntry._

sealed trait MessageType extends EnumEntry with Lowercase

object MessageType extends Enum[MessageType] with CirceEnum[MessageType] with DoobieEnum[MessageType] {

case object Trace extends MessageType
case object Debug extends MessageType
case object Info extends MessageType
case object Warn extends MessageType
case object Error extends MessageType
case object Fatal extends MessageType

override def values: IndexedSeq[MessageType] = findValues
}
8 changes: 8 additions & 0 deletions ce3/src/main/scala/doobiex/enums/data.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
INSERT
INTO messages (typ, msg)
VALUES
('warn', 'message_warn'),
('fatal', 'message_fatal'),
('debug', 'message_debug'),
('trace', 'message_trace'),
('error', 'message_error');
10 changes: 10 additions & 0 deletions ce3/src/main/scala/doobiex/enums/meta.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

create type message_type AS ENUM('trace', 'debug', 'info', 'warn', 'error', 'fatal');

create table if not exists messages
(
id uuid default uuid_generate_v4() not null constraint messages_pk primary key,
typ message_type,
msg text
);
23 changes: 23 additions & 0 deletions ce3/src/main/scala/doobiex/json/InstancesJsonGet.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package doobiex.json

import cats.Show
import cats.data.NonEmptyList
import cats.implicits._
import doobie._
import io.circe._
import org.postgresql.util.PGobject

object InstancesJsonGet {

implicit val showPGobject: Show[PGobject] = Show.show(_.getValue)

implicit val jsonGet: Get[Json] =
Get.Advanced
.other[PGobject](NonEmptyList.of("json"))
.temap[Json] { o: PGobject =>
val parsed: Either[ParsingFailure, Json] = io.circe.parser.parse(o.getValue)
val remapped: Either[String, Json] = parsed.leftMap(_.show)
remapped
}

}
24 changes: 24 additions & 0 deletions ce3/src/main/scala/doobiex/json/InstancesJsonMeta.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package doobiex.json

import cats.implicits._
import doobie._
import io.circe.Json
import org.postgresql.util.PGobject

object InstancesJsonMeta {

implicit val JsonbMeta: Meta[Json] = Meta.Advanced
.other[PGobject]("jsonb")
.timap[Json] { pgo: PGobject =>
io.circe.parser
.parse(pgo.getValue)
.leftMap[Json](err => throw err)
.merge
} { json: Json =>
val o = new PGobject
o.setType("jsonb")
o.setValue(json.noSpaces)
o
}

}
26 changes: 26 additions & 0 deletions ce3/src/main/scala/doobiex/json/JsonMappingApp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package doobiex.json

import cats.effect._
import cats.implicits._
import doobie.implicits._
import doobiex.xa
import io.circe.Json
import java.util.UUID
import doobiex.uuid.InstancesUuidMeta

object JsonMappingApp extends IOApp.Simple {

import InstancesUuidMeta._
import InstancesJsonMeta._
case class Row(id: UUID, value: Option[Json])

val program = sql"select id, value from jsons"
.query[Row]
.to[List]

override def run: IO[Unit] =
program
.transact(xa[IO])
.flatMap(x => x.traverse_(x => IO(pprint.pprintln(x))))

}
25 changes: 25 additions & 0 deletions ce3/src/main/scala/doobiex/uuid/InstancesUuidMeta.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package doobiex.uuid

import doobie.Meta
import java.util.UUID

object InstancesUuidMeta {

/** the rule how to Map Scala types to Postgres
*
* `Meta[A] = Get[A] + Put[A]`
*
* actually, just a map + contramap combination.
* In case of `UUID` we describe two functions:
*
* - `String => UUID`
* - `UUID => String`
*/
implicit val uuidMeta: Meta[UUID] =
Meta[String].imap { raw: String =>
UUID.fromString(raw)
} { uuid: UUID =>
uuid.toString
}

}
42 changes: 42 additions & 0 deletions ce3/src/main/scala/doobiex/uuid/UuidMappingApp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package doobiex.uuid

import cats.effect._
import cats.implicits._
import doobie._
import doobie.implicits._
import doobiex.xa
import java.util.UUID

/** Postgres extensions to handle UUID generation
* {{{
* CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
* }}}
* it allows syntax
* {{{
* id uuid default uuid_generate_v4()
* }}}
*/
object UuidMappingApp extends IOApp.Simple {

/** required to derive Get[MyRow]
* import MetaInstances._
*/

import InstancesUuidMeta._

case class MyRow(id: UUID)

/** Meta combines Get & Put */

val program: ConnectionIO[List[MyRow]] = sql"select id from uuids"
.query[MyRow]
.to[List]

val io: IO[List[MyRow]] = program.transact(xa[IO])

override def run: IO[Unit] =
program
.transact(xa[IO])
.flatMap(_.traverse_(x => IO(pprint.pprintln(x))))

}
6 changes: 6 additions & 0 deletions ce3/src/main/scala/doobiex/uuid/meta.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

create table if not exists uuids
(
id uuid default uuid_generate_v4() not null constraint uuids_pk primary key
);
12 changes: 11 additions & 1 deletion typesafe/src/main/scala/slickvt/Impl.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package slickvt

import akka.NotUsed
import akka.stream.scaladsl.Source
import akka.stream.Materializer
import akka.stream.scaladsl.{Keep, Sink, Source}
import model._
import slick.jdbc.PostgresProfile.api.{Tag => _, _}
import slick.lifted.Rep
import slickvt.model.TagFilter.{ExcludesOnly, IncludesAndExcludes, IncludesOnly}
import slickvt.model.TargetStrategies._

import scala.concurrent.ExecutionContext

trait Impl extends StreamOps with SlickStreamingQueryOps {

private def negateBy(strategy: TargetStrategy): Rep[Boolean] => Rep[Boolean] =
Expand Down Expand Up @@ -54,6 +57,8 @@ trait Impl extends StreamOps with SlickStreamingQueryOps {


private def doFindProfilesWithTags(request: RQuery) = {


val profilesFiltered = mkProfilesFilter(request)
val tagsFiltered = mkTagsFilter(request)

Expand Down Expand Up @@ -86,4 +91,9 @@ trait Impl extends StreamOps with SlickStreamingQueryOps {
.map { case (p, ts) => p -> ts.flatten }
}

def findProfileWithTags(request: RQuery)(implicit m: Materializer, ec: ExecutionContext) = findProfilesWithTagsSource(request)
.toMat(Sink.seq)(Keep.right)
.run()
.map(_.headOption)

}

0 comments on commit 338e7ab

Please sign in to comment.