net.protocol.Bind.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of skunk-core_2.12 Show documentation
Show all versions of skunk-core_2.12 Show documentation
Tagless, non-blocking data access library for Postgres.
The newest version!
// Copyright (c) 2018-2021 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT
package skunk.net.protocol
import cats.effect.Resource
import cats.syntax.all._
import cats.MonadError
import skunk.exception.PostgresErrorException
import skunk.net.message.{ Bind => BindMessage, Close => _, _ }
import skunk.net.MessageSocket
import skunk.net.Protocol.{ PreparedStatement, PortalId }
import skunk.util.{ Origin, Namer }
import natchez.Trace
trait Bind[F[_]] {
def apply[A](
statement: PreparedStatement[F, A],
args: A,
argsOrigin: Origin
): Resource[F, PortalId]
}
object Bind {
def apply[F[_]: Exchange: MessageSocket: Namer: Trace](
implicit ev: MonadError[F, Throwable]
): Bind[F] =
new Bind[F] {
override def apply[A](
statement: PreparedStatement[F, A],
args: A,
argsOrigin: Origin
): Resource[F, PortalId] =
Resource.make {
exchange("bind") {
for {
pn <- nextName("portal").map(PortalId(_))
ea = statement.statement.encoder.encode(args) // encoded args
_ <- Trace[F].put(
"arguments" -> ea.map(_.orNull).mkString(","),
"portal-id" -> pn.value
)
_ <- send(BindMessage(pn.value, statement.id.value, ea))
_ <- send(Flush)
_ <- flatExpect {
case BindComplete => ().pure[F]
case ErrorResponse(info) =>
for {
hi <- history(Int.MaxValue)
_ <- send(Sync)
_ <- expect { case ReadyForQuery(_) => }
a <- PostgresErrorException.raiseError[F, Unit](
sql = statement.statement.sql,
sqlOrigin = Some(statement.statement.origin),
info = info,
history = hi,
arguments = statement.statement.encoder.types.zip(ea),
argumentsOrigin = Some(argsOrigin)
)
} yield a
}
} yield pn
}
} { Close[F].apply }
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy