Skip to content

Commit

Permalink
Revert "finagle-mysql: Support unsigned integer"
Browse files Browse the repository at this point in the history
Summary: This reverts commit ba1438af3971129c7e6c80080efdf669a7fde4e3.

This commit is based on a Github PR, #618, and the authorship wasn't merged
correctly so this will revert the work, then a follow up will revert-the-revert to
fix the authorship.

Differential Revision: https://phabricator.twitter.biz/D80814
  • Loading branch information
Bryce Anderson authored and jenkins committed Aug 14, 2017
1 parent 8500e00 commit 7cf3a02
Show file tree
Hide file tree
Showing 16 changed files with 125 additions and 466 deletions.
10 changes: 0 additions & 10 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ New Features
* finagle-init: Introduce a module to support service-loading initialization
code. ``PHAB_ID=D75950``

* finagle-mysql: Add support for unsigned integers. When enabled, unsigned integers that do
not fit into the existing signed representation are widened. For example an unsigned
Int32 is represented as a Java Long, etc. Because this changes the `c.t.f.mysql.Value`
variant returned by the row, it is disabled by default and must be enabled with the param
`c.t.f.Mysql.param.UnsignedColumns`. ``PHAB_ID=D78721``

* finagle-netty4: Adds support for passing a chain file to the default TLS implementation.
``PHAB_ID=D59531``

Expand Down Expand Up @@ -106,10 +100,6 @@ Breaking API Changes
* finagle-memcached: Add `c.t.util.Closable` trait to `c.t.f.memcached.BaseClient`.
``PHAB_ID=D63970``

* finagle-mysql: A number of implementation details were made private such as specific
`Row` implementations and `ResultSet` builder functions that consume raw packets.
``PHAB_ID=D78721``

* finagle-serversets: Remove `ZkMetaData.AddressOrdering``, it is no longer used.
``PHAB_ID=D60698``

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class ClientSessionTest extends FunSuite with MockitoSugar {
testSessionStatus(
"mysql-dispatcher", { tr: Transport[mysql.transport.Packet, mysql.transport.Packet] =>
val handshake = mysql.Handshake(Some("username"), Some("password"))
val dispatcher = new mysql.ClientDispatcher(tr, handshake, false)
val dispatcher = new mysql.ClientDispatcher(tr, handshake)
() =>
dispatcher.status
}
Expand Down
35 changes: 3 additions & 32 deletions finagle-mysql/src/main/scala/com/twitter/finagle/Mysql.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ import java.net.SocketAddress
*/
trait MysqlRichClient { self: com.twitter.finagle.Client[Request, Result] =>

/**
* Whether the client supports unsigned integer fields
*/
protected val supportUnsigned: Boolean

def richClientStatsReceiver: StatsReceiver = NullStatsReceiver

/**
Expand All @@ -42,14 +37,14 @@ trait MysqlRichClient { self: com.twitter.finagle.Client[Request, Result] =>
dest: Name,
label: String
): mysql.Client with mysql.Transactions with mysql.Cursors =
mysql.Client(newClient(dest, label), richClientStatsReceiver, supportUnsigned)
mysql.Client(newClient(dest, label), richClientStatsReceiver)

/**
* Creates a new `RichClient` connected to the logical
* destination described by `dest`.
*/
def newRichClient(dest: String): mysql.Client with mysql.Transactions with mysql.Cursors =
mysql.Client(newClient(dest), richClientStatsReceiver, supportUnsigned)
mysql.Client(newClient(dest), richClientStatsReceiver)
}

object MySqlClientTracingFilter {
Expand Down Expand Up @@ -94,8 +89,6 @@ object MySqlClientTracingFilter {
*/
object Mysql extends com.twitter.finagle.Client[Request, Result] with MysqlRichClient {

protected val supportUnsigned = param.UnsignedColumns.param.default.supported

object param {

/**
Expand All @@ -114,25 +107,6 @@ object Mysql extends com.twitter.finagle.Client[Request, Result] with MysqlRichC
object MaxConcurrentPrepareStatements {
implicit val param = Stack.Param(MaxConcurrentPrepareStatements(20))
}

/**
* Configure whether to support unsigned integer fields should be considered when
* returning elements of a [[Row]]. If not supported, unsigned fields will be decoded
* as if they were signed, potentially resulting in corruption in the case of overflowing
* the signed representation. Because Java doesn't support unsigned integer types
* widening may be necessary to support the unsigned variants. For example, an unsigned
* Int is represented as a Long.
*
* `Value` representations of unsigned columns which are widened when enabled:
* `ByteValue` -> `ShortValue``
* `ShortValue` -> IntValue`
* `LongValue` -> `LongLongValue`
* `LongLongValue` -> `BigIntValue`
*/
case class UnsignedColumns(supported: Boolean)
object UnsignedColumns {
implicit val param = Stack.Param(UnsignedColumns(false))
}
}

object Client {
Expand Down Expand Up @@ -167,8 +141,6 @@ object Mysql extends com.twitter.finagle.Client[Request, Result] with MysqlRichC
with WithDefaultLoadBalancer[Client]
with MysqlRichClient {

protected val supportUnsigned = params[param.UnsignedColumns].supported

protected def copy1(
stack: Stack[ServiceFactory[Request, Result]] = this.stack,
params: Stack.Params = this.params
Expand All @@ -195,8 +167,7 @@ object Mysql extends com.twitter.finagle.Client[Request, Result] with MysqlRichC
mysql.ClientDispatcher(
transport.map(_.toBuf, Packet.fromBuf),
Handshake(params),
num,
supportUnsigned
num
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,122 +18,92 @@ trait CanBeParameter[-A] { outer =>
}

object CanBeParameter {
implicit val stringCanBeParameter: CanBeParameter[String] = {
implicit val stringCanBeParameter = {
new CanBeParameter[String] {
def sizeOf(param: String): Int = {
val bytes = param.getBytes(Charset.defaultCharset)
MysqlBuf.sizeOfLen(bytes.size) + bytes.size
}

def typeCode(param: String): Short = Type.VarChar
def write(writer: MysqlBufWriter, param: String): Unit =
def typeCode(param: String) = Type.VarChar
def write(writer: MysqlBufWriter, param: String) = {
writer.writeLengthCodedString(param, Charset.defaultCharset)
}
}
}

implicit val booleanCanBeParameter: CanBeParameter[Boolean] = {
implicit val booleanCanBeParameter = {
new CanBeParameter[Boolean] {
def sizeOf(param: Boolean): Int = 1
def typeCode(param: Boolean): Short = Type.Tiny
def write(writer: MysqlBufWriter, param: Boolean): Unit =
writer.writeByte(if (param) 1 else 0)
def sizeOf(param: Boolean) = 1
def typeCode(param: Boolean) = Type.Tiny
def write(writer: MysqlBufWriter, param: Boolean) = writer.writeByte(if (param) 1 else 0)
}
}

implicit val byteCanBeParameter: CanBeParameter[Byte] = {
implicit val byteCanBeParameter = {
new CanBeParameter[Byte] {
def sizeOf(param: Byte): Int = 1
def typeCode(param: Byte): Short = Type.Tiny
def write(writer: MysqlBufWriter, param: Byte): Unit =
writer.writeByte(param)
def sizeOf(param: Byte) = 1
def typeCode(param: Byte) = Type.Tiny
def write(writer: MysqlBufWriter, param: Byte) = writer.writeByte(param)
}
}

implicit val shortCanBeParameter: CanBeParameter[Short] = {
implicit val shortCanBeParameter = {
new CanBeParameter[Short] {
def sizeOf(param: Short): Int = 2
def typeCode(param: Short): Short = Type.Short
def write(writer: MysqlBufWriter, param: Short): Unit =
writer.writeShortLE(param)
def sizeOf(param: Short) = 2
def typeCode(param: Short) = Type.Short
def write(writer: MysqlBufWriter, param: Short) = writer.writeShortLE(param)
}
}

implicit val intCanBeParameter: CanBeParameter[Int] = {
implicit val intCanBeParameter = {
new CanBeParameter[Int] {
def sizeOf(param: Int): Int = 4
def typeCode(param: Int): Short = Type.Long
def write(writer: MysqlBufWriter, param: Int): Unit =
writer.writeIntLE(param)
def sizeOf(param: Int) = 4
def typeCode(param: Int) = Type.Long
def write(writer: MysqlBufWriter, param: Int) = writer.writeIntLE(param)
}
}

implicit val longCanBeParameter = {
new CanBeParameter[Long] {
def sizeOf(param: Long): Int = 8
def typeCode(param: Long): Short = Type.LongLong
def write(writer: MysqlBufWriter, param: Long): Unit =
writer.writeLongLE(param)
}
}

implicit val bigIntCanBeParameter: CanBeParameter[BigInt] = {
new CanBeParameter[BigInt] {
def sizeOf(param: BigInt): Int = 8
def typeCode(param: BigInt): Short = Type.LongLong
def write(writer: MysqlBufWriter, param: BigInt): Unit = {
val byteArray: Array[Byte] = param.toByteArray
val lengthOfByteArray: Int = byteArray.length

if (lengthOfByteArray > 8) {
throw new BigIntTooLongException(size = lengthOfByteArray)
}

for (i <- (lengthOfByteArray - 1) to 0 by -1) {
writer.writeByte(byteArray(i))
}

for (i <- lengthOfByteArray until 8) {
writer.writeByte(0x0)
}
}
def sizeOf(param: Long) = 8
def typeCode(param: Long) = Type.LongLong
def write(writer: MysqlBufWriter, param: Long) = writer.writeLongLE(param)
}
}

implicit val floatCanBeParameter: CanBeParameter[Float] = {
implicit val floatCanBeParameter = {
new CanBeParameter[Float] {
def sizeOf(param: Float): Int = 4
def typeCode(param: Float): Short = Type.Float
def write(writer: MysqlBufWriter, param: Float): Unit =
writer.writeFloatLE(param)
def sizeOf(param: Float) = 4
def typeCode(param: Float) = Type.Float
def write(writer: MysqlBufWriter, param: Float) = writer.writeFloatLE(param)
}
}

implicit val doubleCanBeParameter: CanBeParameter[Double] = {
implicit val doubleCanBeParameter = {
new CanBeParameter[Double] {
def sizeOf(param: Double): Int = 8
def typeCode(param: Double): Short = Type.Double
def write(writer: MysqlBufWriter, param: Double): Unit =
writer.writeDoubleLE(param)
def sizeOf(param: Double) = 8
def typeCode(param: Double) = Type.Double
def write(writer: MysqlBufWriter, param: Double) = writer.writeDoubleLE(param)
}
}

implicit val byteArrayCanBeParameter: CanBeParameter[Array[Byte]] = {
implicit val byteArrayCanBeParameter = {
new CanBeParameter[Array[Byte]] {
def sizeOf(param: Array[Byte]): Int = MysqlBuf.sizeOfLen(param.length) + param.length
def typeCode(param: Array[Byte]): Short = {
def sizeOf(param: Array[Byte]) = MysqlBuf.sizeOfLen(param.length) + param.length
def typeCode(param: Array[Byte]) = {
if (param.length <= 255) Type.TinyBlob
else if (param.length <= 65535) Type.Blob
else if (param.length <= 16777215) Type.MediumBlob
else -1
}
def write(writer: MysqlBufWriter, param: Array[Byte]): Unit =
writer.writeLengthCodedBytes(param)
def write(writer: MysqlBufWriter, param: Array[Byte]) = writer.writeLengthCodedBytes(param)
}
}

implicit val valueCanBeParameter: CanBeParameter[Value] = {
implicit val valueCanBeParameter = {
new CanBeParameter[Value] {
def sizeOf(param: Value): Int = param match {
def sizeOf(param: Value) = param match {
case RawValue(_, _, true, b) => MysqlBuf.sizeOfLen(b.length) + b.length
case StringValue(s) =>
val bytes = s.getBytes(Charset.defaultCharset);
Expand All @@ -142,82 +112,76 @@ object CanBeParameter {
case ShortValue(_) => 2
case IntValue(_) => 4
case LongValue(_) => 8
case BigIntValue(_) => 8
case FloatValue(_) => 4
case DoubleValue(_) => 8
case NullValue => 0
case _ => 0
}

def typeCode(param: Value): Short = param match {
def typeCode(param: Value) = param match {
case RawValue(typ, _, _, _) => typ
case StringValue(_) => Type.VarChar
case ByteValue(_) => Type.Tiny
case ShortValue(_) => Type.Short
case IntValue(_) => Type.Long
case LongValue(_) => Type.LongLong
case BigIntValue(_) => Type.LongLong
case FloatValue(_) => Type.Float
case DoubleValue(_) => Type.Double
case EmptyValue => -1
case NullValue => Type.Null
}

def write(writer: MysqlBufWriter, param: Value): Unit = param match {
def write(writer: MysqlBufWriter, param: Value) = param match {
// allows for generic binary values as params to a prepared statement.
case RawValue(_, _, true, bytes) => writer.writeLengthCodedBytes(bytes)
// allows for Value types as params to prepared statements
case ByteValue(b) => writer.writeByte(b)
case ShortValue(s) => writer.writeShortLE(s)
case IntValue(i) => writer.writeIntLE(i)
case LongValue(l) => writer.writeLongLE(l)
case BigIntValue(b) => bigIntCanBeParameter.write(writer, b)
case FloatValue(f) => writer.writeFloatLE(f)
case DoubleValue(d) => writer.writeDoubleLE(d)
case StringValue(s) => writer.writeLengthCodedString(s, Charset.defaultCharset)
case _ => ()
}
}
}

implicit val timestampCanBeParameter: CanBeParameter[java.sql.Timestamp] = {
implicit val timestampCanBeParameter = {
new CanBeParameter[java.sql.Timestamp] {
def sizeOf(param: java.sql.Timestamp): Int = 12
def typeCode(param: java.sql.Timestamp): Short = Type.Timestamp
def write(writer: MysqlBufWriter, param: java.sql.Timestamp): Unit = {
def sizeOf(param: java.sql.Timestamp) = 12
def typeCode(param: java.sql.Timestamp) = Type.Timestamp
def write(writer: MysqlBufWriter, param: java.sql.Timestamp) = {
valueCanBeParameter.write(writer, TimestampValue(param))
}
}
}

implicit val sqlDateCanBeParameter: CanBeParameter[java.sql.Date] = {
implicit val sqlDateCanBeParameter = {
new CanBeParameter[java.sql.Date] {
def sizeOf(param: java.sql.Date): Int = 5
def typeCode(param: java.sql.Date): Short = Type.Date
def write(writer: MysqlBufWriter, param: java.sql.Date): Unit = {
def sizeOf(param: java.sql.Date) = 5
def typeCode(param: java.sql.Date) = Type.Date
def write(writer: MysqlBufWriter, param: java.sql.Date) = {
valueCanBeParameter.write(writer, DateValue(param))
}
}
}

implicit val javaDateCanBeParameter: CanBeParameter[java.util.Date] = {
implicit val javaDateCanBeParameter = {
new CanBeParameter[java.util.Date] {
def sizeOf(param: java.util.Date): Int = 12
def typeCode(param: java.util.Date): Short = Type.DateTime
def write(writer: MysqlBufWriter, param: java.util.Date): Unit = {
def sizeOf(param: java.util.Date) = 12
def typeCode(param: java.util.Date) = Type.DateTime
def write(writer: MysqlBufWriter, param: java.util.Date) = {
valueCanBeParameter.write(writer, TimestampValue(new java.sql.Timestamp(param.getTime)))
}
}
}

implicit val nullCanBeParameter: CanBeParameter[Null] = {
implicit val nullCanBeParameter = {
new CanBeParameter[Null] {
def sizeOf(param: Null): Int = 0
def typeCode(param: Null): Short = Type.Null
def sizeOf(param: Null) = 0
def typeCode(param: Null) = Type.Null
def write(writer: MysqlBufWriter, param: Null): Unit = ()
}
}
}

class BigIntTooLongException(size: Int)
extends Exception(
s"BigInt is stored as Unsigned Long, thus it cannot be longer than 8 bytes. Size = $size"
)

0 comments on commit 7cf3a02

Please sign in to comment.