Skip to content

Commit

Permalink
fix deprecated EOF support for MySQL 5.5 and 5.6
Browse files Browse the repository at this point in the history
  • Loading branch information
tanner0101 committed Jun 15, 2018
1 parent d542b2e commit b050392
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 46 deletions.
4 changes: 2 additions & 2 deletions Sources/MySQL/Connection/MySQLConnection+Query.swift
Expand Up @@ -12,7 +12,7 @@ extension MySQLConnection {
var rows: [[MySQLColumn: MySQLData]] = []
return self.query(query) { row in
rows.append(row)
}.map(to: [[MySQLColumn: MySQLData]].self) {
}.map {
return rows
}
}
Expand Down Expand Up @@ -66,7 +66,7 @@ extension MySQLConnection {
)
let comClose = MySQLPacket.ComStmtClose(statementID: ok.statementID)
var columns: [MySQLColumnDefinition41] = []
return self.send([.comStmtExecute(comExecute), .comStmtClose(comClose)]) { message in
return self.send([.comStmtExecute(comExecute)]) { message in
switch message {
case .columnDefinition41(let col):
columns.append(col)
Expand Down
9 changes: 5 additions & 4 deletions Sources/MySQL/Connection/MySQLConnection.swift
Expand Up @@ -67,16 +67,17 @@ public final class MySQLConnection: BasicWorker, DatabaseConnection {

/// Sends `MySQLPacket` to the server.
internal func send(_ messages: [MySQLPacket], onResponse: @escaping (MySQLPacket) throws -> Bool) -> Future<Void> {
// if the connection is closed, fail immidiately
guard !isClosed else {
return eventLoop.newFailedFuture(error: closeError)
}

// if currentSend is not nil, previous send has not completed
assert(currentSend == nil, "Attempting to call `send(...)` again before previous invocation has completed.")
switch handler.state {
case .waiting: break
default: assertionFailure("Attempting to call `send(...)` while handler is still: \(handler.state).")
}
// if the connection is closed, fail immidiately
guard !isClosed else {
return eventLoop.newFailedFuture(error: closeError)
}

// create a new promise and store it
let promise = eventLoop.newPromise(Void.self)
Expand Down
14 changes: 11 additions & 3 deletions Sources/MySQL/Connection/MySQLConnectionHandler.swift
Expand Up @@ -34,7 +34,7 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
// MARK: Private

private func handlePacket(ctx: ChannelHandlerContext, packet: MySQLPacket) throws {
// print("✅ \(packet) \(state)")
print("\(packet) \(state)")
switch state {
case .nascent:
switch packet {
Expand Down Expand Up @@ -149,8 +149,16 @@ final class MySQLConnectionHandler: ChannelInboundHandler {
}

func errorCaught(ctx: ChannelHandlerContext, error: Error) {
readyForQuery?.fail(error: error)
readyForQuery = nil
switch state {
case .nascent:
readyForQuery?.fail(error: error)
readyForQuery = nil
case .callback(let promise, _):
self.state = .waiting
promise.fail(error: error)
case .waiting:
ERROR("Error while waiting: \(error).")
}
}

/// Ask the server if it supports SSL and adds a new OpenSSLClientHandler to pipeline if it does
Expand Down
24 changes: 16 additions & 8 deletions Sources/MySQL/Pipeline/MySQLPacketDecoder.swift
Expand Up @@ -198,6 +198,7 @@ final class MySQLPacketDecoder: ByteToMessageDecoder {

/// Statement Protocol (Prepared Query)
func decodeStatementProtocol(ctx: ChannelHandlerContext, buffer: inout ByteBuffer, statementState: MySQLStatementProtocolState, capabilities: MySQLCapabilities) throws -> DecodingState {
print(statementState)
switch statementState {
case .waitingPrepare:
// check for error packet
Expand Down Expand Up @@ -232,6 +233,13 @@ final class MySQLPacketDecoder: ByteToMessageDecoder {
remaining -= 1
if remaining == 0 {
session.connectionState = .statement(.paramsDone(ok: ok))
if !capabilities.contains(.CLIENT_DEPRECATE_EOF) {
let res = try decodeBasicPacket(ctx: ctx, buffer: &buffer, capabilities: capabilities, forwarding: false)
switch res {
case .needMoreData: return .needMoreData
default: break
}
}
} else {
session.connectionState = .statement(.params(ok: ok, remaining: remaining))
}
Expand All @@ -242,10 +250,6 @@ final class MySQLPacketDecoder: ByteToMessageDecoder {
} else {
session.connectionState = .statement(.columnsDone)
}

if !capabilities.contains(.CLIENT_DEPRECATE_EOF) {
return try decodeBasicPacket(ctx: ctx, buffer: &buffer, capabilities: capabilities, forwarding: false)
}
case .columns(var remaining):
guard let _ = try buffer.checkPacketLength(source: .capture()) else {
return .needMoreData
Expand All @@ -257,15 +261,19 @@ final class MySQLPacketDecoder: ByteToMessageDecoder {
remaining -= 1
if remaining == 0 {
session.connectionState = .statement(.columnsDone)
if !capabilities.contains(.CLIENT_DEPRECATE_EOF) {
let res = try decodeBasicPacket(ctx: ctx, buffer: &buffer, capabilities: capabilities, forwarding: false)
switch res {
case .needMoreData: return .needMoreData
default: break
}
}
} else {
session.connectionState = .statement(.columns(remaining: remaining))
}

ctx.fireChannelRead(wrapInboundOut(.columnDefinition41(column)))
case .columnsDone:
if !capabilities.contains(.CLIENT_DEPRECATE_EOF) {
return try decodeBasicPacket(ctx: ctx, buffer: &buffer, capabilities: capabilities, forwarding: false)
}
case .columnsDone: break
case .waitingExecute:
// check for error or OK packet
let peek = buffer.peekInteger(as: Byte.self, skipping: 4)
Expand Down
2 changes: 1 addition & 1 deletion Sources/MySQL/Pipeline/MySQLPacketEncoder.swift
Expand Up @@ -21,7 +21,7 @@ final class MySQLPacketEncoder: MessageToByteEncoder {
/// - data: The data to encode into a `ByteBuffer`.
/// - out: The `ByteBuffer` into which we want to encode.
func encode(ctx: ChannelHandlerContext, data message: MySQLPacket, out: inout ByteBuffer) throws {
// print("➡️ \(message)")
print("➡️ \(message)")
// print("\(#function) \(session.handshakeState)")
let writeOffset = out.writerIndex
out.write(bytes: [0x00, 0x00, 0x00, 0x00]) // save room for length
Expand Down
1 change: 1 addition & 0 deletions Tests/MySQLTests/MySQLTests.swift
Expand Up @@ -19,6 +19,7 @@ class MySQLTests: XCTestCase {
"hello".convertToMySQLData(),
"world".convertToMySQLData()
])).wait()
print(results)
try XCTAssertEqual(results[0].firstValue(forColumn: "test")?.decode(String.self), "helloworld")
print(results)
}
Expand Down
49 changes: 21 additions & 28 deletions circle.yml
@@ -1,21 +1,6 @@
version: 2

jobs:


macos:
macos:
xcode: "9.2"
steps:
- run: brew install mysql
- run: brew services start mysql
- run: sleep 3 && mysqladmin -uroot create test
- checkout
- run: swift build
- run: echo "CREATE DATABASE vapor_test" | mysql -uroot
# - run: swift build -c release
- run: swift test

5.5-linux:
docker:
- image: codevapor/swift:4.1
Expand All @@ -34,7 +19,24 @@ jobs:
- run:
name: Run unit tests
command: swift test

5.6-linux:
docker:
- image: codevapor/swift:4.1
- image: mysql:5.6
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: true
MYSQL_DATABASE: vapor_database
# MYSQL_ROOT_HOST: %
MYSQL_USER: vapor_username
MYSQL_PASSWORD: vapor_password
steps:
- checkout
- run:
name: Compile code
command: swift build
- run:
name: Run unit tests
command: swift test
5.7-linux:
docker:
- image: codevapor/swift:4.1
Expand All @@ -53,7 +55,6 @@ jobs:
- run:
name: Run unit tests
command: swift test

8.0-linux:
docker:
- image: codevapor/swift:4.1
Expand All @@ -72,7 +73,6 @@ jobs:
- run:
name: Run unit tests
command: swift test -Xswiftc -DSSL_TESTS

mariadb-10.3-linux:
docker:
- image: codevapor/swift:4.1
Expand All @@ -91,7 +91,6 @@ jobs:
- run:
name: Run unit tests
command: swift test

8.0-linux-fluent:
docker:
- image: codevapor/swift:4.1
Expand All @@ -114,7 +113,6 @@ jobs:
name: Run Fluent MySQL unit tests
command: swift test
working_directory: ~/fluent-mysql

linux-release:
docker:
- image: codevapor/swift:4.1
Expand All @@ -123,29 +121,24 @@ jobs:
- run:
name: Compile code with optimizations
command: swift build -c release


workflows:
version: 2
tests:
jobs:
# - macos
# - 5.5-linux
- 5.5-linux
- 5.6-linux
- 5.7-linux
- 8.0-linux
- 8.0-linux-fluent
- mariadb-10.3-linux
- linux-release

nightly:
triggers:
- schedule:
cron: "0 0 * * *"
filters:
branches:
only:
- master

- master
jobs:
- 8.0-linux
# - macos
18 changes: 18 additions & 0 deletions docker-compose.yml
Expand Up @@ -19,3 +19,21 @@ services:
MYSQL_PASSWORD: vapor_password
ports:
- 3306:3306
mysql-56:
image: mysql:5.6
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
MYSQL_DATABASE: vapor_database
MYSQL_USER: vapor_username
MYSQL_PASSWORD: vapor_password
ports:
- 3306:3306
mysql-55:
image: mysql:5.5
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
MYSQL_DATABASE: vapor_database
MYSQL_USER: vapor_username
MYSQL_PASSWORD: vapor_password
ports:
- 3306:3306

0 comments on commit b050392

Please sign in to comment.