8000 Merge branch 'master' into master · jasync-sql/jasync-sql@c8313ef · GitHub
[go: up one dir, main page]

Skip to content

Commit c8313ef

Browse files
authored
Merge branch 'master' into master
2 parents 7c702c8 + a5a881f commit c8313ef

File tree

13 files changed

+120
-12
lines changed

13 files changed

+120
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
* Switch to Java Date/Time API from Joda Time [#233](https://github.com/jasync-sql/jasync-sql/pull/233)
66
* For postgresql, add support for threeten.PeriodDuration for interval data type. [#233](https://github.com/jasync-sql/jasync-sql/pull/233)
77

8+
## 1.2.3
9+
10+
* Enable CLIENT_FOUND_ROWS in r2dbc-mysql in favor of spring-data-r2dbc [#240](https://github.com/jasync-sql/jasync-sql/pull/240).
11+
* Fix SSL Connection to MySQL [#237](https://github.com/jasync-sql/jasync-sql/pull/237).
12+
* Add explicit dependency on kotlin-reflect.
13+
814
## 1.2.1
915

1016
* Deploy directly to maven central [#232](https://github.com/jasync-sql/jasync-sql/pull/232).

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/MySQLConnection.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import com.github.jasync.sql.db.mysql.codec.MySQLConnectionHandler
1515
import com.github.jasync.sql.db.mysql.codec.MySQLHandlerDelegate
1616
import com.github.jasync.sql.db.mysql.exceptions.MySQLException
1717
import com.github.jasync.sql.db.mysql.message.client.AuthenticationSwitchResponse
18+
import com.github.jasync.sql.db.mysql.message.client.CapabilityRequestMessage
1819
import com.github.jasync.sql.db.mysql.message.client.HandshakeResponseMessage
19-
import com.github.jasync.sql.db.mysql.message.client.SSLRequestMessage
2020
import com.github.jasync.sql.db.mysql.message.server.AuthenticationSwitchRequest
2121
import com.github.jasync.sql.db.mysql.message.server.EOFMessage
2222
import com.github.jasync.sql.db.mysql.message.server.ErrorMessage
@@ -61,6 +61,7 @@ class MySQLConnection @JvmOverloads constructor(
6161
@Suppress("unused")
6262
val MicrosecondsVersion = Version(5, 6, 0)
6363
private val regexForCallInQueryStart = Regex("\\s*call\\s+.*", RegexOption.IGNORE_CASE)
64+
const val CLIENT_FOUND_ROWS_PROP_NAME = "jasync.mysql.CLIENT_FOUND_ROWS"
6465
}
6566

6667
init {
@@ -262,8 +263,14 @@ class MySQLConnection @JvmOverloads constructor(
262263
}
263264
}
264265

265-
val sslRequest = SSLRequestMessage(setOfNotNull(
266+
val clientFoundRows = System.getProperty(CLIENT_FOUND_ROWS_PROP_NAME) != null
267+
if (clientFoundRows) {
268+
logger.debug { "CLIENT_FOUND_ROWS capability set" }
269+
}
270+
271+
val capabilities = CapabilityRequestMessage(setOfNotNull(
266272
CapabilityFlag.CLIENT_PLUGIN_AUTH,
273+
CapabilityFlag.CLIENT_FOUND_ROWS.takeIf { clientFoundRows },
267274
CapabilityFlag.CLIENT_PROTOCOL_41,
268275
CapabilityFlag.CLIENT_TRANSACTIONS,
269276
CapabilityFlag.CLIENT_MULTI_RESULTS,
@@ -274,7 +281,7 @@ class MySQLConnection @JvmOverloads constructor(
274281
))
275282

276283
val handshakeResponse = HandshakeResponseMessage(
277-
sslRequest,
284+
capabilities,
278285
configuration.username,
279286
configuration.charset,
280287
message.seed,
@@ -289,7 +296,7 @@ class MySQLConnection @JvmOverloads constructor(
289296
return
290297
}
291298

292-
val channelFuture = connectionHandler.write(sslRequest)
299+
val channelFuture = connectionHandler.write(capabilities)
293300
channelFuture.addListener { sslRequestFuture ->
294301
// connectionHandler.write will handle errors (logging, failing promise, etc) in this case.
295302
if (!sslRequestFuture.isSuccess) return@addListener

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/codec/MySQLConnectionHandler.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import com.github.jasync.sql.db.exceptions.DatabaseException
55
import com.github.jasync.sql.db.general.MutableResultSet
66
import com.github.jasync.sql.db.mysql.binary.BinaryRowDecoder
77
import com.github.jasync.sql.db.mysql.message.client.AuthenticationSwitchResponse
8+
import com.github.jasync.sql.db.mysql.message.client.CapabilityRequestMessage
89
import com.github.jasync.sql.db.mysql.message.client.CloseStatementMessage
910
import com.github.jasync.sql.db.mysql.message.client.HandshakeResponseMessage
1011
import com.github.jasync.sql.db.mysql.message.client.PreparedStatementExecuteMessage
1112
import com.github.jasync.sql.db.mysql.message.client.PreparedStatementPrepareMessage
1213
import com.github.jasync.sql.db.mysql.message.client.QueryMessage
1314
import com.github.jasync.sql.db.mysql.message.client.QuitMessage
14-
import com.github.jasync.sql.db.mysql.message.client.SSLRequestMessage
1515
import com.github.jasync.sql.db.mysql.message.client.SendLongDataMessage
1616
import com.github.jasync.sql.db.mysql.message.server.AuthenticationSwitchRequest
1717
import com.github.jasync.sql.db.mysql.message.server.BinaryRowMessage
@@ -273,7 +273,7 @@ class MySQLConnectionHandler(
273273
}
274274
}
275275

276-
fun write(message: SSLRequestMessage): ChannelFuture = writeAndHandleError(message)
276+
fun write(message: CapabilityRequestMessage): ChannelFuture = writeAndHandleError(message)
277277

278278
fun write(message: HandshakeResponseMessage): ChannelFuture {
279279
decoder.hasDoneHandshake = true

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/codec/MySQLFrameDecoder.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.github.jasync.sql.db.mysql.codec
33
import com.github.jasync.sql.db.exceptions.BufferNotFullyConsumedException
44
import com.github.jasync.sql.db.exceptions.NegativeMessageSizeException
55
import com.github.jasync.sql.db.exceptions.ParserNotAvailableException
6+
import com.github.jasync.sql.db.mysql.decoder.AuthenticationSwitchRequestDecoder
67
import com.github.jasync.sql.db.mysql.decoder.ColumnDefinitionDecoder
78
import com.github.jasync.sql.db.mysql.decoder.ColumnProcessingFinishedDecoder
89
import com.github.jasync.sql.db.mysql.decoder.EOFMessageDecoder
@@ -39,6 +40,7 @@ class MySQLFrameDecoder(val charset: Charset, private val connectionId: String)
3940
private val errorDecoder = ErrorDecoder(charset)
4041
private val okDecoder = OkDecoder(charset)
4142
private val columnDecoder = ColumnDefinitionDecoder(charset, DecoderRegistry(charset))
43+
private val authenticationSwitchRequestDecoder = AuthenticationSwitchRequestDecoder(charset)
4244
private val rowDecoder = ResultSetRowDecoder()
4345
private val preparedStatementPrepareDecoder = PreparedStatementPrepareResponseDecoder()
4446

@@ -128,6 +130,8 @@ class MySQLFrameDecoder(val charset: Charset, private val connectionId: String)
128130
if (this.processingColumns) {
129131
this.processingColumns = false
130132
ColumnProcessingFinishedDecoder
133+
} else if (!isValidEOF(slice)) {
134+
authenticationSwitchRequestDecoder
131135
} else {
132136
this.clear()
133137
EOFMessageDecoder
@@ -169,6 +173,11 @@ class MySQLFrameDecoder(val charset: Charset, private val connectionId: String)
169173
doDecoding(decoder, slice, out)
170174
}
171175

176+
private fun isValidEOF(slice: ByteBuf): Boolean {
177+
// see https://dev.mysql.com/doc/internals/en/packet-EOF_Packet.html
178+
return slice.readableBytes() == 4
179+
}
180+
172181
private fun doDecoding(decoder: MessageDecoder?, slice: ByteBuf, out: MutableList<Any>) {
173182
if (decoder == null) {
174183
slice.readerIndex(slice.readerIndex() - 1)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.github.jasync.sql.db.mysql.decoder
2+
3+
import com.github.jasync.sql.db.mysql.message.server.AuthenticationSwitchRequest
4+
import com.github.jasync.sql.db.mysql.message.server.ServerMessage
5+
import com.github.jasync.sql.db.util.readCString
6+
import io.netty.buffer.ByteBuf
7+
import io.netty.buffer.ByteBufUtil
8+
import java.nio.charset.Charset
9+
10+
class AuthenticationSwitchRequestDecoder(val charset: Charset) : MessageDecoder {
11+
override fun decode(buffer: ByteBuf): ServerMessage {
12+
val method = buffer.readCString(charset)
13+
val bytes: Int = buffer.readableBytes()
14+
val terminal = 0.toByte()
15+
val salt = if (bytes > 0 && buffer.getByte(buffer.writerIndex() - 1) == terminal) ByteBufUtil.getBytes(
16+
buffer,
17+
buffer.readerIndex(),
18+
bytes - 1
19+
) else ByteBufUtil.getBytes(buffer)
20+
return AuthenticationSwitchRequest(method, salt)
21+
}
22+
}

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/encoder/AuthenticationSwitchResponseEncoder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class AuthenticationSwitchResponseEncoder(val charset: Charset) : MessageEncoder
2121
val buffer = ByteBufferUtils.packetBuffer()
2222

2323
val bytes =
24-
authenticator.generateAuthentication(charset, switch.password, switch.request.seed.toByteArray(charset))
24+
authenticator.generateAuthentication(charset, switch.password, switch.request.seed)
2525
buffer.writeBytes(bytes)
2626

2727
return buffer

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/encoder/SSLRequestEncoder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.github.jasync.sql.db.mysql.encoder
22

3+
import com.github.jasync.sql.db.mysql.message.client.CapabilityRequestMessage
34
import com.github.jasync.sql.db.mysql.message.client.ClientMessage
4-
import com.github.jasync.sql.db.mysql.message.client.SSLRequestMessage
55
import com.github.jasync.sql.db.mysql.util.CharsetMapper
66
import com.github.jasync.sql.db.util.ByteBufferUtils
77
import io.netty.buffer.ByteBuf
@@ -15,7 +15,7 @@ class SSLRequestEncoder(private val charset: Charset, private val charsetMapper:
1515
}
1616

1717
override fun encode(message: ClientMessage): ByteBuf {
18-
require(message is SSLRequestMessage)
18+
require(message is CapabilityRequestMessage)
1919
var clientCapabilities = 0
2020

2121
for (flag in message.flags) {

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/message/client/SSLRequestMessage.kt renamed to mysql-async/src/main/java/com/github/jasync/sql/db/mysql/message/client/CapabilityRequestMessage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ package com.github.jasync.sql.db.mysql.message.client
22

33
import com.github.jasync.sql.db.mysql.util.CapabilityFlag
44

5-
data class SSLRequestMessage(val flags: Set<CapabilityFlag>) : ClientMessage(SslRequest)
5+
data class CapabilityRequestMessage(val flags: Set<CapabilityFlag>) : ClientMessage(SslRequest)

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/message/client/HandshakeResponseMessage.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.github.jasync.sql.db.mysql.message.client
33
import java.nio.charset.Charset
44

55
data class HandshakeResponseMessage(
6-
val header: SSLRequestMessage,
6+
val header: CapabilityRequestMessage,
77
val username: String,
88
val charset: Charset,
99
@Suppress("ArrayInDataClass")

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/message/server/AuthenticationSwitchRequest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ package com.github.jasync.sql.db.mysql.message.server
22

33
data class AuthenticationSwitchRequest(
44
val method: String,
5-
val seed: String
5+
val seed: ByteArray
66
) : ServerMessage(ServerMessage.EOF)

mysql-async/src/main/java/com/github/jasync/sql/db/mysql/util/CapabilityFlag.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package com.github.jasync.sql.db.mysql.util
44

55
enum class CapabilityFlag(val value: Int) {
6+
CLIENT_FOUND_ROWS(0x00000002),
67
CLIENT_PROTOCOL_41(0x0200),
78
CLIENT_CONNECT_WITH_DB(0x0008),
89
CLIENT_TRANSACTIONS(0x2000),
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.github.jasync.sql.db.mysql
2+
3+
import org.assertj.core.api.Assertions.assertThat
4+
import org.junit.Test
5+
6+
class UpdateQuerySpec : ConnectionHelper() {
7+
8+
@Test
9+
fun `test rowsAffected on update with CLIENT_FOUND_ROWS capability should return all filtered rows and not just actual change`() {
10+
val tableName = "users_${System.currentTimeMillis()}"
11+
System.getProperties().remove(MySQLConnection.CLIENT_FOUND_ROWS_PROP_NAME)
12+
try {
13+
val createTable = """CREATE TABLE $tableName (
14+
id INT NOT NULL AUTO_INCREMENT ,
15+
name VARCHAR(255) CHARACTER SET 'utf8mb4' NOT NULL ,
16+
PRIMARY KEY (id) );"""
17+
val insert = """INSERT INTO $tableName (name) VALUES ('Boogie Man')"""
18+
val query = "update $tableName set name = 'Boogie Man' where name = 'Boogie Man'"
19+
withConnection { connection ->
20+
assertThat(executeQuery(connection, createTable).rowsAffected).isEqualTo(0)
21+
assertThat(executeQuery(connection, insert).rowsAffected).isEqualTo(1)
22+
val result = executeQuery(connection, query)
23+
assertThat(result.rowsAffected).isEqualTo(0L)
24+
}
25+
System.setProperty(MySQLConnection.CLIENT_FOUND_ROWS_PROP_NAME, "true")
26+
withConnection { connection ->
27+
val resultWithProp = executeQuery(connection, query)
28+
assertThat(resultWithProp.rowsAffected).isEqualTo(1L)
29+
}
30+
} finally {
31+
System.getProperties().remove(MySQLConnection.CLIENT_FOUND_ROWS_PROP_NAME)
32+
}
33+
}
34+
}

r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.jasync.r2dbc.mysql
22

33
import com.github.jasync.sql.db.Configuration
4+
import com.github.jasync.sql.db.mysql.MySQLConnection.Companion.CLIENT_FOUND_ROWS_PROP_NAME
45
import com.github.jasync.sql.db.mysql.pool.MySQLConnectionFactory
56
import io.r2dbc.spi.ConnectionFactoryOptions
67
import io.r2dbc.spi.ConnectionFactoryOptions.CONNECT_TIMEOUT
@@ -13,6 +14,11 @@ import io.r2dbc.spi.ConnectionFactoryOptions.USER
1314
import io.r2dbc.spi.ConnectionFactoryProvider
1415
import io.r2dbc.spi.Option
1516
import java.time.Duration
17+
import kotlin.properties.ReadWriteProperty
18+
import kotlin.reflect.KProperty
19+
import mu.KotlinLogging
20+
21+
private val logger = KotlinLogging.logger {}
1622

1723
class MysqlConnectionFactoryProvider : ConnectionFactoryProvider {
1824

@@ -33,6 +39,29 @@ class MysqlConnectionFactoryProvider : ConnectionFactoryProvider {
3339
* Driver option value.
3440
*/
3541
const val MYSQL_DRIVER = "mysql"
42+
43+
var CLIENT_FOUND_ROWS: Boolean by ClientFoundRowsDelegate()
44+
45+
init {
46+
// see issue https://github.com/jasync-sql/jasync-sql/issues/240
47+
CLIENT_FOUND_ROWS = true
48+
}
49+
50+
class ClientFoundRowsDelegate : ReadWriteProperty<Companion, Boolean> {
51+
override fun getValue(thisRef: Companion, property: KProperty<*>): Boolean {
52+
return System.getProperty(CLIENT_FOUND_ROWS_PROP_NAME) != null
53+
}
54+
55+
override fun setValue(thisRef: Companion, property: KProperty<*>, value: Boolean) {
56+
if (value) {
57+
logger.info { "set $CLIENT_FOUND_ROWS_PROP_NAME=$value" }
58+
System.setProperty(CLIENT_FOUND_ROWS_PROP_NAME, value.toString())
59+
} else {
60+
logger.info { "remove $CLIENT_FOUND_ROWS_PROP_NAME" }
61+
System.getProperties().remove(CLIENT_FOUND_ROWS_PROP_NAME)
62+
}
63+
}
64+
}
3665
}
3766

3867
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")

0 commit comments

Comments
 (0)
0