-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support unsigned integer #618
Changes from 4 commits
a08e174
ae2f56a
8fecffb
9d69d8e
e938863
c4d1470
27c385e
aacf93b
1ed3e45
d6aed81
e219ad1
f296c6b
5eb03e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
package com.twitter.finagle.mysql | ||
|
||
import com.twitter.finagle.mysql.transport.MysqlBuf | ||
import com.twitter.finagle.mysql.transport.{MysqlBuf, MysqlBufReader} | ||
import com.twitter.io.Buf | ||
|
||
/** | ||
|
@@ -71,14 +71,19 @@ class StringEncodedRow(rawRow: Buf, val fields: IndexedSeq[Field], indexMap: Map | |
else { | ||
val str = new String(bytes, Charset(charset)) | ||
field.fieldType match { | ||
case Type.Tiny => ByteValue(str.toByte) | ||
case Type.Short => ShortValue(str.toShort) | ||
case Type.Int24 => IntValue(str.toInt) | ||
case Type.Long => IntValue(str.toInt) | ||
case Type.LongLong => LongValue(str.toLong) | ||
case Type.Float => FloatValue(str.toFloat) | ||
case Type.Double => DoubleValue(str.toDouble) | ||
case Type.Year => ShortValue(str.toShort) | ||
case Type.Tiny if field.isSigned() => ByteValue(str.toByte) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we add a comment as to why we're doing this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah sure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assumed that you're talking about isSigned logic, right? If it is, should I write comments for BinaryEncodedRow too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that would be rad, but I think if you add the helper method you described, that will document it well enough. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That helper method might need implicit parameters, is that OK? Some project might have rules likes "do not use implicits" so I want to ask. |
||
case Type.Tiny => ShortValue(str.toShort) | ||
case Type.Short if field.isSigned() => ShortValue(str.toShort) | ||
case Type.Short => IntValue(str.toInt) | ||
case Type.Int24 if field.isSigned() => IntValue(str.toInt) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can merge ones where it doesn't matter if it's signed or not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I thought it might be good to see all cases in discrete. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like them explicit too, tbh. |
||
case Type.Int24 => IntValue(str.toInt) | ||
case Type.Long if field.isSigned() => IntValue(str.toInt) | ||
case Type.Long => LongValue(str.toLong) | ||
case Type.LongLong if field.isSigned() => LongValue(str.toLong) | ||
case Type.LongLong => BigIntValue(BigInt(str)) | ||
case Type.Float => FloatValue(str.toFloat) | ||
case Type.Double => DoubleValue(str.toDouble) | ||
case Type.Year => ShortValue(str.toShort) | ||
// Nonbinary strings as stored in the CHAR, VARCHAR, and TEXT data types | ||
case Type.VarChar | Type.String | Type.VarString | | ||
Type.TinyBlob | Type.Blob | Type.MediumBlob | ||
|
@@ -101,7 +106,7 @@ class StringEncodedRow(rawRow: Buf, val fields: IndexedSeq[Field], indexMap: Map | |
* [[http://dev.mysql.com/doc/internals/en/binary-protocol-resultset-row.html]] | ||
*/ | ||
class BinaryEncodedRow(rawRow: Buf, val fields: IndexedSeq[Field], indexMap: Map[String, Int]) extends Row { | ||
private val reader = MysqlBuf.reader(rawRow) | ||
private val reader: MysqlBufReader = MysqlBuf.reader(rawRow) | ||
reader.skip(1) | ||
|
||
/** | ||
|
@@ -130,14 +135,19 @@ class BinaryEncodedRow(rawRow: Buf, val fields: IndexedSeq[Field], indexMap: Map | |
for ((field, idx) <- fields.zipWithIndex) yield { | ||
if (isNull(idx)) NullValue | ||
else field.fieldType match { | ||
case Type.Tiny => ByteValue(reader.readByte()) | ||
case Type.Short => ShortValue(reader.readShortLE()) | ||
case Type.Int24 => IntValue(reader.readIntLE()) | ||
case Type.Long => IntValue(reader.readIntLE()) | ||
case Type.LongLong => LongValue(reader.readLongLE()) | ||
case Type.Float => FloatValue(reader.readFloatLE()) | ||
case Type.Double => DoubleValue(reader.readDoubleLE()) | ||
case Type.Year => ShortValue(reader.readShortLE()) | ||
case Type.Tiny if field.isSigned() => ByteValue(reader.readByte()) | ||
case Type.Tiny => ShortValue(reader.readUnsignedByte()) | ||
case Type.Short if field.isSigned() => ShortValue(reader.readShortLE()) | ||
case Type.Short => IntValue(reader.readUnsignedShortLE()) | ||
case Type.Int24 if field.isSigned() => IntValue(reader.readIntLE()) | ||
case Type.Int24 => IntValue(reader.readIntLE()) | ||
case Type.Long if field.isSigned() => IntValue(reader.readIntLE()) | ||
case Type.Long => LongValue(reader.readUnsignedIntLE()) | ||
case Type.LongLong if field.isSigned() => LongValue(reader.readLongLE()) | ||
case Type.LongLong => BigIntValue(reader.readUnsignedLongLE()) | ||
case Type.Float => FloatValue(reader.readFloatLE()) | ||
case Type.Double => DoubleValue(reader.readDoubleLE()) | ||
case Type.Year => ShortValue(reader.readShortLE()) | ||
// Nonbinary strings as stored in the CHAR, VARCHAR, and TEXT data types | ||
case Type.VarChar | Type.String | Type.VarString | | ||
Type.TinyBlob | Type.Blob | Type.MediumBlob | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,4 +67,37 @@ object Type { | |
case NullValue => Null | ||
case _ => -1 | ||
} | ||
|
||
/** | ||
* Retrieves string of the given code. | ||
*/ | ||
private[mysql] def getCodeString(code: Short): String = code match { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this unused? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have added for debugging actually but left as is, it might be helpful. |
||
case Decimal => "Decimal" | ||
case Tiny => "Tiny" | ||
case Short => "Short" | ||
case Long => "Long" | ||
case Float => "Float" | ||
case Double => "Double" | ||
case Null => "Null" | ||
case Timestamp => "Timestamp" | ||
case LongLong => "LongLong" | ||
case Int24 => "Int24" | ||
case Date => "Date" | ||
case Time => "Time" | ||
case DateTime => "DateTime" | ||
case Year => "Year" | ||
case NewDate => "NewDate" | ||
case VarChar => "VarChar" | ||
case Bit => "Bit" | ||
case NewDecimal => "NewDecimal" | ||
case Enum => "Enum" | ||
case Set => "Set" | ||
case TinyBlob => "TinyBlob" | ||
case MediumBlob => "MediumBlob" | ||
case LongBlob => "LongBlob" | ||
case Blob => "Blob" | ||
case VarString => "VarString" | ||
case String => "String" | ||
case Geometry => "Geometry" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,6 +132,30 @@ class MysqlBufReader(buf: Buf) extends ProxyByteReader { | |
case len => throw new IllegalStateException(s"Invalid length byte: $len") | ||
} | ||
} | ||
|
||
private val unsignedLongMaxValue: BigInt = BigInt("18446744073709551615") | ||
|
||
def readUnsignedLongLE(): BigInt = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both of these seem generally useful. Maybe we should move them under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, it is under twitter/util repo, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
val arr = Array.ofDim[Byte](8) | ||
|
||
for (i <- 0 until 8) { | ||
val b = readByte() | ||
arr(7 - i) = b | ||
} | ||
|
||
BigInt(arr) & unsignedLongMaxValue | ||
} | ||
|
||
def readUnsignedLongBE(): BigInt = { | ||
val arr = Array.ofDim[Byte](8) | ||
|
||
for (i <- 0 until 8) { | ||
val b = readByte() | ||
arr(i) = b | ||
} | ||
|
||
BigInt(arr) & unsignedLongMaxValue | ||
} | ||
} | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some style nits for ya that I missed earlier:
We typically leave parens off of these types of methods (both defining and calling) unless they mutate in some way. Since this doesn't, please omit here and in isSigned