Skip to content

Commit

Permalink
Merge pull request #257 from franklinhu/franklin-mysql-injections
Browse files Browse the repository at this point in the history
Add correct String/ChannelBuffer injections
  • Loading branch information
johnynek committed Mar 2, 2015
2 parents 89bad77 + 42ee798 commit 8b6fd5c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ object MySqlValue {
case v: Int => new MySqlValue(IntValue(v))
case v: Long => new MySqlValue(LongValue(v))
case v: Short => new MySqlValue(ShortValue(v))
case v: ChannelBuffer => new MySqlValue(RawValue(Type.String, Charset.Utf8_general_ci, false, v.toString(UTF_8).getBytes))
case v: ChannelBuffer =>
val bytes = Array.ofDim[Byte](v.readableBytes)
v.markReaderIndex()
v.readBytes(bytes)
v.resetReaderIndex()
new MySqlValue(RawValue(Type.Blob, Charset.Binary, isBinary = true, bytes))
case _ => throw new UnsupportedOperationException(v.getClass.getName + " is currently not supported.")
}
}
Expand Down Expand Up @@ -124,21 +129,33 @@ class MySqlValue(val v: Value) {
* Returns string representation of the finagle-mysql Value wrapped by MySqlValue
* Both null values and empty values map to empty string.
*/
@deprecated("Use String2MySqlValueInjection", "0.10.0")
object MySqlStringInjection extends Injection[MySqlValue, String] {
def apply(a: MySqlValue): String = ValueMapper.toString(a.v).getOrElse("") // should this be null: String instead?
override def invert(b: String) = Try(MySqlValue(RawValue(Type.String, Charset.Utf8_general_ci, false, b.getBytes)))
}

object String2MySqlValueInjection extends Injection[String, MySqlValue] {
def apply(s: String): MySqlValue = MySqlValue(s)
override def invert(m: MySqlValue): Try[String] = Try { ValueMapper.toString(m.v).get }
}

/**
* Injection from MySqlValue to ChannelBuffer.
* Returns a channel buffer containing the Value wrapped by MySqlValue.
* Both null values and empty values map to empty channel buffer.
*/
@deprecated("Use ChannelBuffer2MySqlValueInjection", "0.10.0")
object MySqlCbInjection extends Injection[MySqlValue, ChannelBuffer] {
def apply(a: MySqlValue): ChannelBuffer = ValueMapper.toChannelBuffer(a.v).getOrElse(ChannelBuffers.EMPTY_BUFFER)
override def invert(b: ChannelBuffer) = Try(MySqlValue((Type.String, Charset.Utf8_general_ci, false, b.toString(UTF_8))))
}

object ChannelBuffer2MySqlValueInjection extends Injection[ChannelBuffer, MySqlValue] {
def apply(c: ChannelBuffer): MySqlValue = MySqlValue(c)
override def invert(m: MySqlValue): Try[ChannelBuffer] = Try { ValueMapper.toChannelBuffer(m.v).get }
}

object LongMySqlInjection extends Injection[Long, MySqlValue] {
def apply(a: Long): MySqlValue = MySqlValue(a)
override def invert(b: MySqlValue) = Try(ValueMapper.toLong(b.v).get)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2013 Twitter Inc.
*
* Licensed 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.twitter.storehaus.mysql

import java.util.Arrays

import org.jboss.netty.buffer.{ChannelBuffers, ChannelBuffer}
import org.scalacheck.{Gen, Arbitrary, Properties}
import org.scalacheck.Prop.forAll

object MySqlValueInjectionProperties extends Properties("MySqlValue Injections") {

val channelBufferGenerator = for {
b <- Gen.containerOf[Array, Byte](Arbitrary.arbitrary[Byte])
} yield ChannelBuffers.wrappedBuffer(b)

implicit val gen = Arbitrary(channelBufferGenerator)

property("String2MySqlValue apply and invert") = {
val injection = String2MySqlValueInjection
forAll { (s: String) =>
injection.invert(injection(s)).toOption == Some(s)
}
}

property("ChannelBuffer2MySqlValue apply and invert") = {
val injection = ChannelBuffer2MySqlValueInjection

forAll { (c: ChannelBuffer) =>
val bytes = bytesFromChannelBuffer(c)
val inverted = injection.invert(injection(c)).toOption
inverted.exists { invertedBuf =>
val invertedBytes = bytesFromChannelBuffer(invertedBuf)
Arrays.equals(invertedBytes, bytes)
}
}
}

def bytesFromChannelBuffer(c: ChannelBuffer): Array[Byte] = {
val arr = Array.ofDim[Byte](c.readableBytes)
c.markReaderIndex()
c.readBytes(arr)
c.resetReaderIndex()
arr
}
}

0 comments on commit 8b6fd5c

Please sign in to comment.