All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.message.Bind.scala Maven / Gradle / Ivy

// 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.message

import cats.syntax.all._
import scodec.interop.cats._
import scodec._
import scodec.codecs._

case class Bind(portal: String, statement: String, args: List[Option[String]])
  extends TaggedFrontendMessage('B') {
    def encodeBody = Bind.encoder.encode(this)
  }

object Bind {

  val encoder: Encoder[Bind] = {

      // String   - The name of the destination portal (an empty string selects the unnamed portal).
      // String   - The name of the source prepared statement (an empty string selects the unnamed
      //            prepared statement).
      // Int16    - The number of parameter format codes that follow (denoted C below). This can be
      //            zero to indicate that there are no parameters or that the parameters all use the
      //            default format (text); or one, in which case the specified format code is
      //            applied to all parameters; or it can equal the actual number of parameters.
      // Int16[C] - The parameter format codes. Each must presently be zero (text) or one (binary).
      // Int16    - The number of parameter values that follow (possibly zero). This must match the
      //            number of parameters needed by the query.
      //
      // Next, the following pair of fields appear for each parameter:
      //
      // Int32    - The length of the parameter value, in bytes (this count does not include
      //            itself). Can be zero. As a special case, -1 indicates a NULL parameter value.
      //            No value bytes follow in the NULL case.
      // Byten    - The value of the parameter, in the format indicated by the associated format
      //            code. n is the above length.
      //
      // After the last parameter, the following fields appear:
      //
      // Int16    - The number of result-column format codes that follow (denoted R below). This
      //            can be zero to indicate that there are no result columns or that the result
      //            columns should all use the default format (text); or one, in which case the
      //            specified format code is applied to all result columns (if any); or it can equal
      //            the actual number of result columns of the query.
      // Int16[R] - The result-column format codes. Each must presently be zero (text) or one
      //            (binary).

      val arg: Codec[Option[String]] =
        Codec(
          Encoder { (os: Option[String]) =>
            os match {
              case None    => int32.encode(-1)
              case Some(s) =>
                for {
                  data <- utf8.encode(s)
                  len  <- int32.encode(data.size.toInt / 8)
                } yield len ++ data
            }
          },
          null // :-\
        )

      (utf8z.asEncoder, utf8z.asEncoder, int16.asEncoder, int16.asEncoder, list(arg).asEncoder, int16.asEncoder).contramapN[Bind] { b => (
        b.portal      ,  // The name of the destination portal
        b.statement   , // The name of the source prepared statement
        0             , // The number of parameter format codes
        b.args.length , // The number of parameter values
        b.args        , // args
        0               // The number of result-column format codes
      )}

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy