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

com.github.mauricio.async.db.mysql.encoder.PreparedStatementExecuteEncoder.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013 Maurício Linhares
 *
 * Maurício Linhares licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.github.mauricio.async.db.mysql.encoder

import io.netty.buffer.{ByteBuf, Unpooled}
import com.github.mauricio.async.db.mysql.column.ColumnTypes
import com.github.mauricio.async.db.mysql.binary.BinaryRowEncoder
import com.github.mauricio.async.db.mysql.message.client.{
  PreparedStatementExecuteMessage,
  ClientMessage
}
import com.github.mauricio.async.db.util.ByteBufferUtils
import scala.collection.Seq

class PreparedStatementExecuteEncoder(rowEncoder: BinaryRowEncoder)
    extends MessageEncoder {

  def encode(message: ClientMessage): ByteBuf = {
    val m = message.asInstanceOf[PreparedStatementExecuteMessage]

    val buffer = ByteBufferUtils.packetBuffer()
    buffer.writeByte(m.kind)
    buffer.writeBytes(m.statementId)
    buffer.writeByte(0x00) // no cursor
    buffer.writeInt(1)

    if (m.parameters.isEmpty) {
      buffer
    } else {
      Unpooled.wrappedBuffer(buffer, encodeValues(m.values, m.valuesToInclude))
    }

  }

  private[encoder] def encodeValues(
    values: Seq[Any],
    valuesToInclude: Set[Int]
  ): ByteBuf = {
    val nullBitsCount         = (values.size + 7) / 8
    val nullBits              = new Array[Byte](nullBitsCount)
    val bitMapBuffer          = ByteBufferUtils.mysqlBuffer(1 + nullBitsCount)
    val parameterTypesBuffer  = ByteBufferUtils.mysqlBuffer(values.size * 2)
    val parameterValuesBuffer = ByteBufferUtils.mysqlBuffer()

    var index = 0

    while (index < values.length) {
      val value = values(index)
      if (value == null || value == None) {
        nullBits(index / 8) =
          (nullBits(index / 8) | (1 << (index & 7))).asInstanceOf[Byte]
        parameterTypesBuffer.writeShort(ColumnTypes.FIELD_TYPE_NULL)
      } else {
        value match {
          case Some(v) =>
            encodeValue(
              parameterTypesBuffer,
              parameterValuesBuffer,
              v,
              valuesToInclude(index)
            )
          case _ =>
            encodeValue(
              parameterTypesBuffer,
              parameterValuesBuffer,
              value,
              valuesToInclude(index)
            )
        }
      }
      index += 1
    }

    bitMapBuffer.writeBytes(nullBits)
    if (values.size > 0) {
      bitMapBuffer.writeByte(1)
    } else {
      bitMapBuffer.writeByte(0)
    }

    Unpooled.wrappedBuffer(
      bitMapBuffer,
      parameterTypesBuffer,
      parameterValuesBuffer
    )
  }

  private def encodeValue(
    parameterTypesBuffer: ByteBuf,
    parameterValuesBuffer: ByteBuf,
    value: Any,
    includeValue: Boolean
  ): Unit = {
    val encoder = rowEncoder.encoderFor(value)
    parameterTypesBuffer.writeShort(encoder.encodesTo)
    if (includeValue)
      encoder.encode(value, parameterValuesBuffer)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy