Skip to content

Commit b8adc6c

Browse files
committed
Adding support for MySQL BIT type - fixes mauricio#48
1 parent 8765606 commit b8adc6c

28 files changed

+93
-64
lines changed

db-async-common/src/main/scala/com/github/mauricio/async/db/util/ChannelUtils.scala renamed to db-async-common/src/main/scala/com/github/mauricio/async/db/util/ByteBufferUtils.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import java.nio.charset.Charset
2020
import java.nio.ByteOrder
2121
import io.netty.buffer.{Unpooled, ByteBuf}
2222

23-
object ChannelUtils {
23+
object ByteBufferUtils {
2424

2525
def writeLength(buffer: ByteBuf) {
2626

db-async-common/src/main/scala/com/github/mauricio/async/db/util/ChannelWrapper.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ class ChannelWrapper( val buffer : ByteBuf ) extends AnyVal {
3939
new String( bytes, charset )
4040
}
4141

42-
def readCString( charset : Charset ) = ChannelUtils.readCString(buffer, charset)
42+
def readCString( charset : Charset ) = ByteBufferUtils.readCString(buffer, charset)
4343

44-
def readUntilEOF( charset: Charset ) = ChannelUtils.readUntilEOF(buffer, charset)
44+
def readUntilEOF( charset: Charset ) = ByteBufferUtils.readUntilEOF(buffer, charset)
4545

4646
def read3BytesInt : Int = {
4747
val first = buffer.readByte()
@@ -106,7 +106,7 @@ class ChannelWrapper( val buffer : ByteBuf ) extends AnyVal {
106106
}
107107

108108
def writePacketLength( sequence : Int = 0 ) {
109-
ChannelUtils.writePacketLength(buffer, sequence )
109+
ByteBufferUtils.writePacketLength(buffer, sequence )
110110
}
111111

112112
}

db-async-common/src/main/scala/com/github/mauricio/async/db/util/NettyUtils.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ import io.netty.channel.nio.NioEventLoopGroup
1919

2020
object NettyUtils {
2121

22-
lazy val DetaultEventLoopGroup = new NioEventLoopGroup(0, DaemonThreadsFactory)
22+
lazy val DefaultEventLoopGroup = new NioEventLoopGroup(0, DaemonThreadsFactory)
2323

2424
}

db-async-common/src/test/scala/com/github/mauricio/async/db/util/ChannelUtilsSpec.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,19 @@ class ChannelUtilsSpec extends Specification {
3030
val content = "some text"
3131
val buffer = Unpooled.buffer()
3232

33-
ChannelUtils.writeCString(content, buffer, charset)
33+
ByteBufferUtils.writeCString(content, buffer, charset)
3434

35-
ChannelUtils.readCString(buffer, charset) === content
35+
ByteBufferUtils.readCString(buffer, charset) === content
3636
buffer.readableBytes() === 0
3737
}
3838

3939
"correctly read the buggy MySQL EOF string when there is an EOF" in {
4040
val content = "some text"
4141
val buffer = Unpooled.buffer()
4242

43-
ChannelUtils.writeCString(content, buffer, charset)
43+
ByteBufferUtils.writeCString(content, buffer, charset)
4444

45-
ChannelUtils.readUntilEOF(buffer, charset) === content
45+
ByteBufferUtils.readUntilEOF(buffer, charset) === content
4646
buffer.readableBytes() === 0
4747
}
4848

@@ -53,7 +53,7 @@ class ChannelUtilsSpec extends Specification {
5353

5454
buffer.writeBytes(content.getBytes(charset))
5555

56-
ChannelUtils.readUntilEOF(buffer, charset) === content
56+
ByteBufferUtils.readUntilEOF(buffer, charset) === content
5757
buffer.readableBytes() === 0
5858

5959
}

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/MySQLConnection.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ object MySQLConnection {
4141
class MySQLConnection(
4242
configuration: Configuration,
4343
charsetMapper: CharsetMapper = CharsetMapper.Instance,
44-
group : EventLoopGroup = NettyUtils.DetaultEventLoopGroup,
44+
group : EventLoopGroup = NettyUtils.DefaultEventLoopGroup,
4545
executionContext : ExecutionContext = ExecutorServiceUtils.CachedExecutionContext
4646
)
4747
extends MySQLHandlerDelegate

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/binary/BinaryRowEncoder.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ class BinaryRowEncoder( charset : Charset ) {
6969

7070
val nullBitsCount = (values.size + 7) / 8
7171
val nullBits = new Array[Byte](nullBitsCount)
72-
val bitMapBuffer = ChannelUtils.mysqlBuffer(1 + nullBitsCount)
73-
val parameterTypesBuffer = ChannelUtils.mysqlBuffer(values.size * 2)
74-
val parameterValuesBuffer = ChannelUtils.mysqlBuffer()
72+
val bitMapBuffer = ByteBufferUtils.mysqlBuffer(1 + nullBitsCount)
73+
val parameterTypesBuffer = ByteBufferUtils.mysqlBuffer(values.size * 2)
74+
val parameterValuesBuffer = ByteBufferUtils.mysqlBuffer()
7575

7676

7777
var index = 0

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/codec/DecoderRegistry.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class DecoderRegistry(charset: Charset) {
4949
this.stringDecoder
5050
}
5151
}
52+
case ColumnTypes.FIELD_TYPE_BIT => ByteArrayDecoder
5253
case ColumnTypes.FIELD_TYPE_LONGLONG => LongDecoder
5354
case ColumnTypes.FIELD_TYPE_LONG | ColumnTypes.FIELD_TYPE_INT24 => IntegerDecoder
5455
case ColumnTypes.FIELD_TYPE_YEAR | ColumnTypes.FIELD_TYPE_SHORT => ShortDecoder
@@ -87,6 +88,7 @@ class DecoderRegistry(charset: Charset) {
8788
ColumnTypes.FIELD_TYPE_STRING |
8889
ColumnTypes.FIELD_TYPE_ENUM => StringEncoderDecoder
8990
case ColumnTypes.FIELD_TYPE_YEAR => ShortEncoderDecoder
91+
case ColumnTypes.FIELD_TYPE_BIT => ByteArrayColumnDecoder
9092
case ColumnTypes.FIELD_TYPE_BLOB => {
9193
if (charsetCode == CharsetMapper.Binary) {
9294
ByteArrayColumnDecoder

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/codec/MySQLFrameDecoder.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package com.github.mauricio.async.db.mysql.codec
1919
import com.github.mauricio.async.db.exceptions._
2020
import com.github.mauricio.async.db.mysql.decoder._
2121
import com.github.mauricio.async.db.mysql.message.server._
22-
import com.github.mauricio.async.db.util.ChannelUtils.read3BytesInt
22+
import com.github.mauricio.async.db.util.ByteBufferUtils.read3BytesInt
2323
import com.github.mauricio.async.db.util.ChannelWrapper.bufferToWrapper
2424
import com.github.mauricio.async.db.util.Log
2525
import io.netty.buffer.ByteBuf

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/codec/MySQLOneToOneEncoder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import com.github.mauricio.async.db.mysql.binary.BinaryRowEncoder
2121
import com.github.mauricio.async.db.mysql.encoder._
2222
import com.github.mauricio.async.db.mysql.message.client.ClientMessage
2323
import com.github.mauricio.async.db.mysql.util.CharsetMapper
24-
import com.github.mauricio.async.db.util.{ChannelUtils, Log}
24+
import com.github.mauricio.async.db.util.{ByteBufferUtils, Log}
2525
import java.nio.charset.Charset
2626
import scala.annotation.switch
2727
import io.netty.channel.ChannelHandlerContext
@@ -68,7 +68,7 @@ class MySQLOneToOneEncoder(charset: Charset, charsetMapper: CharsetMapper) exten
6868

6969
val result = encoder.encode(message)
7070

71-
ChannelUtils.writePacketLength(result, sequence)
71+
ByteBufferUtils.writePacketLength(result, sequence)
7272

7373
sequence += 1
7474

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/decoder/HandshakeV10Decoder.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package com.github.mauricio.async.db.mysql.decoder
1818

1919
import io.netty.buffer.ByteBuf
2020
import com.github.mauricio.async.db.mysql.message.server.{HandshakeMessage, ServerMessage}
21-
import com.github.mauricio.async.db.util.{Log, ChannelUtils}
21+
import com.github.mauricio.async.db.util.{Log, ByteBufferUtils}
2222
import java.nio.charset.Charset
2323

2424
object HandshakeV10Decoder {
@@ -34,7 +34,7 @@ class HandshakeV10Decoder(charset: Charset) extends MessageDecoder {
3434

3535
def decode(buffer: ByteBuf): ServerMessage = {
3636

37-
val serverVersion = ChannelUtils.readCString(buffer, charset)
37+
val serverVersion = ByteBufferUtils.readCString(buffer, charset)
3838
val connectionId = buffer.readInt()
3939

4040
var seed = new Array[Byte]( SeedSize + SeedComplementSize )
@@ -56,7 +56,7 @@ class HandshakeV10Decoder(charset: Charset) extends MessageDecoder {
5656
buffer.readerIndex(buffer.readerIndex() + Padding)
5757
buffer.readBytes(seed, SeedSize, SeedComplementSize)
5858
buffer.readByte()
59-
authenticationMethod = Some(ChannelUtils.readUntilEOF(buffer, charset))
59+
authenticationMethod = Some(ByteBufferUtils.readUntilEOF(buffer, charset))
6060
}
6161

6262
new HandshakeMessage(

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/encoder/HandshakeResponseEncoder.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import com.github.mauricio.async.db.exceptions.UnsupportedAuthenticationMethodEx
2121
import com.github.mauricio.async.db.mysql.encoder.auth.MySQLNativePasswordAuthentication
2222
import com.github.mauricio.async.db.mysql.message.client.{HandshakeResponseMessage, ClientMessage}
2323
import com.github.mauricio.async.db.mysql.util.CharsetMapper
24-
import com.github.mauricio.async.db.util.{Log, ChannelUtils}
24+
import com.github.mauricio.async.db.util.{Log, ByteBufferUtils}
2525
import java.nio.charset.Charset
2626

2727
object HandshakeResponseEncoder {
@@ -66,13 +66,13 @@ class HandshakeResponseEncoder(charset: Charset, charsetMapper: CharsetMapper) e
6666
clientCapabilities |= CLIENT_CONNECT_WITH_DB
6767
}
6868

69-
val buffer = ChannelUtils.packetBuffer()
69+
val buffer = ByteBufferUtils.packetBuffer()
7070

7171
buffer.writeInt(clientCapabilities)
7272
buffer.writeInt(MAX_3_BYTES)
7373
buffer.writeByte(charsetMapper.toInt(charset))
7474
buffer.writeBytes(PADDING)
75-
ChannelUtils.writeCString( m.username, buffer, charset )
75+
ByteBufferUtils.writeCString( m.username, buffer, charset )
7676

7777
if ( m.password.isDefined ) {
7878
val method = m.authenticationMethod.get
@@ -86,11 +86,11 @@ class HandshakeResponseEncoder(charset: Charset, charsetMapper: CharsetMapper) e
8686
}
8787

8888
if ( m.database.isDefined ) {
89-
ChannelUtils.writeCString( m.database.get, buffer, charset )
89+
ByteBufferUtils.writeCString( m.database.get, buffer, charset )
9090
}
9191

9292
if ( m.authenticationMethod.isDefined ) {
93-
ChannelUtils.writeCString( m.authenticationMethod.get, buffer, charset )
93+
ByteBufferUtils.writeCString( m.authenticationMethod.get, buffer, charset )
9494
} else {
9595
buffer.writeByte(0)
9696
}

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/encoder/PreparedStatementExecuteEncoder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ package com.github.mauricio.async.db.mysql.encoder
1919
import io.netty.buffer.{ByteBuf, Unpooled}
2020
import com.github.mauricio.async.db.mysql.binary.BinaryRowEncoder
2121
import com.github.mauricio.async.db.mysql.message.client.{PreparedStatementExecuteMessage, ClientMessage}
22-
import com.github.mauricio.async.db.util.ChannelUtils
22+
import com.github.mauricio.async.db.util.ByteBufferUtils
2323

2424
class PreparedStatementExecuteEncoder( rowEncoder : BinaryRowEncoder ) extends MessageEncoder {
2525

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

29-
val buffer = ChannelUtils.packetBuffer()
29+
val buffer = ByteBufferUtils.packetBuffer()
3030
buffer.writeByte( m.kind )
3131
buffer.writeBytes(m.statementId)
3232
buffer.writeByte(0x00) // no cursor

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/encoder/PreparedStatementPrepareEncoder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ package com.github.mauricio.async.db.mysql.encoder
1818

1919
import io.netty.buffer.ByteBuf
2020
import com.github.mauricio.async.db.mysql.message.client.{PreparedStatementPrepareMessage, ClientMessage}
21-
import com.github.mauricio.async.db.util.ChannelUtils
21+
import com.github.mauricio.async.db.util.ByteBufferUtils
2222
import java.nio.charset.Charset
2323

2424
class PreparedStatementPrepareEncoder( charset : Charset ) extends MessageEncoder {
2525

2626
def encode(message: ClientMessage): ByteBuf = {
2727
val m = message.asInstanceOf[PreparedStatementPrepareMessage]
2828
val statement = m.statement.getBytes(charset)
29-
val buffer = ChannelUtils.packetBuffer( 4 + 1 + statement.size)
29+
val buffer = ByteBufferUtils.packetBuffer( 4 + 1 + statement.size)
3030
buffer.writeByte( m.kind )
3131
buffer.writeBytes( statement )
3232

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/encoder/QueryMessageEncoder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package com.github.mauricio.async.db.mysql.encoder
1818

1919
import io.netty.buffer.ByteBuf
2020
import com.github.mauricio.async.db.mysql.message.client.{QueryMessage, ClientMessage}
21-
import com.github.mauricio.async.db.util.ChannelUtils
21+
import com.github.mauricio.async.db.util.ByteBufferUtils
2222
import java.nio.charset.Charset
2323

2424
class QueryMessageEncoder( charset : Charset ) extends MessageEncoder {
@@ -27,7 +27,7 @@ class QueryMessageEncoder( charset : Charset ) extends MessageEncoder {
2727

2828
val m = message.asInstanceOf[QueryMessage]
2929
val encodedQuery = m.query.getBytes( charset )
30-
val buffer = ChannelUtils.packetBuffer(4 + 1 + encodedQuery.length )
30+
val buffer = ByteBufferUtils.packetBuffer(4 + 1 + encodedQuery.length )
3131
buffer.writeByte( ClientMessage.Query )
3232
buffer.writeBytes( encodedQuery )
3333

mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/encoder/QuitMessageEncoder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ package com.github.mauricio.async.db.mysql.encoder
1818

1919
import io.netty.buffer.ByteBuf
2020
import com.github.mauricio.async.db.mysql.message.client.ClientMessage
21-
import com.github.mauricio.async.db.util.ChannelUtils
21+
import com.github.mauricio.async.db.util.ByteBufferUtils
2222

2323
object QuitMessageEncoder extends MessageEncoder {
2424

2525
def encode(message: ClientMessage): ByteBuf = {
26-
val buffer = ChannelUtils.packetBuffer(5)
26+
val buffer = ByteBufferUtils.packetBuffer(5)
2727
buffer.writeByte( ClientMessage.Quit )
2828
buffer
2929
}

mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/QuerySpec.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,33 @@ class QuerySpec extends Specification with ConnectionHelper {
162162

163163
}
164164

165+
"support BIT type" in {
166+
167+
val create =
168+
"""CREATE TEMPORARY TABLE POSTS (
169+
| id INT NOT NULL AUTO_INCREMENT,
170+
| bit_column BIT(20),
171+
| primary key (id))
172+
""".stripMargin
173+
174+
val insert = "INSERT INTO POSTS (bit_column) VALUES (b'10000000')"
175+
val select = "SELECT * FROM POSTS"
176+
177+
withConnection {
178+
connection =>
179+
executeQuery(connection, create)
180+
executeQuery(connection, insert)
181+
182+
val rows = executeQuery(connection, select).rows.get
183+
rows(0)("bit_column") === Array(0,0,-128)
184+
185+
val preparedRows = executePreparedStatement(connection, select).rows.get
186+
preparedRows(0)("bit_column") === Array(0,0,-128)
187+
188+
}
189+
190+
}
191+
165192
}
166193

167194
}

mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/codec/MySQLFrameDecoderSpec.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package com.github.mauricio.async.db.mysql.codec
1919
import io.netty.buffer.ByteBuf
2020
import io.netty.util.CharsetUtil
2121
import com.github.mauricio.async.db.mysql.message.server._
22-
import com.github.mauricio.async.db.util.ChannelUtils
22+
import com.github.mauricio.async.db.util.ByteBufferUtils
2323
import com.github.mauricio.async.db.util.ChannelWrapper.bufferToWrapper
2424
import org.specs2.mutable.Specification
2525
import com.github.mauricio.async.db.mysql.message.server.OkMessage
@@ -119,7 +119,7 @@ class MySQLFrameDecoderSpec extends Specification {
119119

120120
decoder.totalColumns === 0
121121

122-
val columnCountBuffer = ChannelUtils.packetBuffer()
122+
val columnCountBuffer = ByteBufferUtils.packetBuffer()
123123
columnCountBuffer.writeLength(2)
124124
columnCountBuffer.writePacketLength()
125125

@@ -148,7 +148,7 @@ class MySQLFrameDecoderSpec extends Specification {
148148

149149
decoder.processingColumns must beFalse
150150

151-
val row = ChannelUtils.packetBuffer()
151+
val row = ByteBufferUtils.packetBuffer()
152152
row.writeLenghtEncodedString("1", charset)
153153
row.writeLenghtEncodedString("some name", charset)
154154
row.writePacketLength()
@@ -171,7 +171,7 @@ class MySQLFrameDecoderSpec extends Specification {
171171
}
172172

173173
def createOkPacket() : ByteBuf = {
174-
val buffer = ChannelUtils.packetBuffer()
174+
val buffer = ByteBufferUtils.packetBuffer()
175175
buffer.writeByte(0)
176176
buffer.writeLength(10)
177177
buffer.writeLength(15)
@@ -183,7 +183,7 @@ class MySQLFrameDecoderSpec extends Specification {
183183
}
184184

185185
def createErrorPacket(content : String) : ByteBuf = {
186-
val buffer = ChannelUtils.packetBuffer()
186+
val buffer = ByteBufferUtils.packetBuffer()
187187
buffer.writeByte(0xff)
188188
buffer.writeShort(27)
189189
buffer.writeByte('H')
@@ -194,7 +194,7 @@ class MySQLFrameDecoderSpec extends Specification {
194194
}
195195

196196
def createColumnPacket( name : String, columnType : Int ) : ByteBuf = {
197-
val buffer = ChannelUtils.packetBuffer()
197+
val buffer = ByteBufferUtils.packetBuffer()
198198
buffer.writeLenghtEncodedString("def", charset)
199199
buffer.writeLenghtEncodedString("some_schema", charset)
200200
buffer.writeLenghtEncodedString("some_table", charset)
@@ -213,7 +213,7 @@ class MySQLFrameDecoderSpec extends Specification {
213213
}
214214

215215
def createEOFPacket() : ByteBuf = {
216-
val buffer = ChannelUtils.packetBuffer()
216+
val buffer = ByteBufferUtils.packetBuffer()
217217
buffer.writeByte(0xfe)
218218
buffer.writeShort(879)
219219
buffer.writeShort(8765)

postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/PostgreSQLConnection.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class PostgreSQLConnection
4545
configuration: Configuration = Configuration.Default,
4646
encoderRegistry: ColumnEncoderRegistry = PostgreSQLColumnEncoderRegistry.Instance,
4747
decoderRegistry: ColumnDecoderRegistry = PostgreSQLColumnDecoderRegistry.Instance,
48-
group : EventLoopGroup = NettyUtils.DetaultEventLoopGroup,
48+
group : EventLoopGroup = NettyUtils.DefaultEventLoopGroup,
4949
executionContext : ExecutionContext = ExecutorServiceUtils.CachedExecutionContext
5050
)
5151
extends PostgreSQLConnectionDelegate

postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/encoders/CredentialEncoder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package com.github.mauricio.async.db.postgresql.encoders
1919
import com.github.mauricio.async.db.postgresql.messages.backend.{ServerMessage, AuthenticationResponseType}
2020
import com.github.mauricio.async.db.postgresql.messages.frontend.{CredentialMessage, ClientMessage}
2121
import com.github.mauricio.async.db.postgresql.util.PasswordHelper
22-
import com.github.mauricio.async.db.util.ChannelUtils
22+
import com.github.mauricio.async.db.util.ByteBufferUtils
2323
import java.nio.charset.Charset
2424
import io.netty.buffer.{Unpooled, ByteBuf}
2525

@@ -48,7 +48,7 @@ class CredentialEncoder(charset: Charset) extends Encoder {
4848
buffer.writeBytes(password)
4949
buffer.writeByte(0)
5050

51-
ChannelUtils.writeLength(buffer)
51+
ByteBufferUtils.writeLength(buffer)
5252

5353
buffer
5454
}

0 commit comments

Comments
 (0)