Skip to content

Commit 3ca32b8

Browse files
mp911deschauder
authored andcommitted
#75 - Add support for MySQL using jasync-mysql.
We now support MySQL through the jasync-mysql driver that exposes its asynchronous functionality through a R2DBC wrapper implementation. Jasync uses for now its own exceptions. Original pull request: #84.
1 parent 08d91bd commit 3ca32b8

11 files changed

+525
-6
lines changed

pom.xml

+22-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
<degraph-check.version>0.1.4</degraph-check.version>
3232
<hsqldb.version>2.4.1</hsqldb.version>
3333
<postgresql.version>42.2.5</postgresql.version>
34+
<mysql.version>5.1.47</mysql.version>
35+
<jasync.version>0.9.38</jasync.version>
3436
<mssql-jdbc.version>7.1.2.jre8-preview</mssql-jdbc.version>
3537
<r2dbc-releasetrain.version>Arabba-M7</r2dbc-releasetrain.version>
3638
<reactive-streams.version>1.0.1</reactive-streams.version>
@@ -173,6 +175,13 @@
173175
<scope>test</scope>
174176
</dependency>
175177

178+
<dependency>
179+
<groupId>mysql</groupId>
180+
<artifactId>mysql-connector-java</artifactId>
181+
<version>${mysql.version}</version>
182+
<scope>test</scope>
183+
</dependency>
184+
176185
<dependency>
177186
<groupId>com.microsoft.sqlserver</groupId>
178187
<artifactId>mssql-jdbc</artifactId>
@@ -198,6 +207,13 @@
198207
<scope>test</scope>
199208
</dependency>
200209

210+
<dependency>
211+
<groupId>com.github.jasync-sql</groupId>
212+
<artifactId>jasync-r2dbc-mysql</artifactId>
213+
<version>${jasync.version}</version>
214+
<scope>test</scope>
215+
</dependency>
216+
201217
<dependency>
202218
<groupId>de.schauderhaft.degraph</groupId>
203219
<artifactId>degraph-check</artifactId>
@@ -295,7 +311,8 @@
295311
<querydslVersion>${querydsl}</querydslVersion>
296312
<springVersion>${spring}</springVersion>
297313
<r2dbcVersion>${r2dbc-spi.version}</r2dbcVersion>
298-
<reactiveStreamsVersion>${reactive-streams.version}</reactiveStreamsVersion>
314+
<reactiveStreamsVersion>${reactive-streams.version}
315+
</reactiveStreamsVersion>
299316
<releasetrainVersion>${releasetrain}</releasetrainVersion>
300317
<allow-uri-read>true</allow-uri-read>
301318
<toclevels>3</toclevels>
@@ -416,6 +433,10 @@
416433
<id>spring-libs-snapshot</id>
417434
<url>https://repo.spring.io/libs-snapshot</url>
418435
</repository>
436+
<repository>
437+
<id>jcenter</id>
438+
<url>https://jcenter.bintray.com/</url>
439+
</repository>
419440
</repositories>
420441

421442
<pluginRepositories>

src/main/java/org/springframework/data/r2dbc/dialect/AnonymousBindMarkers.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* https://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,

src/main/java/org/springframework/data/r2dbc/dialect/Database.java

+12
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ public String driverName() {
5353
public Dialect defaultDialect() {
5454
return H2Dialect.INSTANCE;
5555
}
56+
},
57+
58+
MYSQL {
59+
@Override
60+
public String driverName() {
61+
return "MySQL";
62+
}
63+
64+
@Override
65+
public Dialect defaultDialect() {
66+
return MySqlDialect.INSTANCE;
67+
}
5668
};
5769

5870
/**

src/main/java/org/springframework/data/r2dbc/dialect/IndexedBindMarker.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* https://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.r2dbc.dialect;
17+
18+
import java.net.InetAddress;
19+
import java.net.URI;
20+
import java.net.URL;
21+
import java.util.Arrays;
22+
import java.util.Collection;
23+
import java.util.HashSet;
24+
import java.util.Set;
25+
import java.util.UUID;
26+
27+
/**
28+
* An SQL dialect for MySQL.
29+
*
30+
* @author Mark Paluch
31+
*/
32+
public class MySqlDialect implements Dialect {
33+
34+
private static final Set<Class<?>> SIMPLE_TYPES = new HashSet<>(
35+
Arrays.asList(UUID.class, URL.class, URI.class, InetAddress.class));
36+
37+
/**
38+
* Singleton instance.
39+
*/
40+
public static final MySqlDialect INSTANCE = new MySqlDialect();
41+
42+
private static final BindMarkersFactory ANONYMOUS = BindMarkersFactory.anonymous("?");
43+
44+
private static final LimitClause LIMIT_CLAUSE = new LimitClause() {
45+
46+
/*
47+
* (non-Javadoc)
48+
* @see org.springframework.data.r2dbc.dialect.LimitClause#getClause(long, long)
49+
*/
50+
@Override
51+
public String getClause(long limit, long offset) {
52+
return String.format("LIMIT %d,%d", limit, offset);
53+
}
54+
55+
/*
56+
* (non-Javadoc)
57+
* @see org.springframework.data.r2dbc.dialect.LimitClause#getClause(long)
58+
*/
59+
@Override
60+
public String getClause(long limit) {
61+
return "LIMIT " + limit;
62+
}
63+
64+
/*
65+
* (non-Javadoc)
66+
* @see org.springframework.data.r2dbc.dialect.LimitClause#getClausePosition()
67+
*/
68+
@Override
69+
public Position getClausePosition() {
70+
return Position.END;
71+
}
72+
};
73+
74+
/*
75+
* (non-Javadoc)
76+
* @see org.springframework.data.r2dbc.dialect.Dialect#getBindMarkersFactory()
77+
*/
78+
@Override
79+
public BindMarkersFactory getBindMarkersFactory() {
80+
return ANONYMOUS;
81+
}
82+
83+
/*
84+
* (non-Javadoc)
85+
* @see org.springframework.data.r2dbc.dialect.Dialect#getSimpleTypesKeys()
86+
*/
87+
@Override
88+
public Collection<? extends Class<?>> getSimpleTypes() {
89+
return SIMPLE_TYPES;
90+
}
91+
92+
/*
93+
* (non-Javadoc)
94+
* @see org.springframework.data.r2dbc.dialect.Dialect#limit()
95+
*/
96+
@Override
97+
public LimitClause limit() {
98+
return LIMIT_CLAUSE;
99+
}
100+
101+
/*
102+
* (non-Javadoc)
103+
* @see org.springframework.data.r2dbc.dialect.Dialect#getArraySupport()
104+
*/
105+
@Override
106+
public ArrayColumns getArraySupport() {
107+
return ArrayColumns.Unsupported.INSTANCE;
108+
}
109+
}

src/test/java/org/springframework/data/r2dbc/dialect/AnonymousBindMarkersUnitTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* https://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,

src/test/java/org/springframework/data/r2dbc/function/AbstractTransactionalDatabaseClientIntegrationTests.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import org.junit.Before;
3434
import org.junit.Test;
35+
3536
import org.springframework.dao.DataAccessException;
3637
import org.springframework.data.r2dbc.testing.R2dbcIntegrationTestSupport;
3738
import org.springframework.jdbc.core.JdbcTemplate;
@@ -201,15 +202,21 @@ public void shouldRollbackTransaction() {
201202
assertThat(count).isEqualTo(0);
202203
}
203204

204-
@Test // gh-2
205+
@Test // gh-2, gh-75
205206
public void emitTransactionIds() {
206207

207208
TransactionalDatabaseClient databaseClient = TransactionalDatabaseClient.create(connectionFactory);
208209

209210
Flux<Object> transactionIds = databaseClient.inTransaction(db -> {
210211

212+
Mono<Integer> insert = db.execute().sql(getInsertIntoLegosetStatement()) //
213+
.bind(0, 42055) //
214+
.bind(1, "SCHAUFELRADBAGGER") //
215+
.bindNull(2, Integer.class) //
216+
.fetch().rowsUpdated();
217+
211218
Flux<Object> txId = db.execute().sql(getCurrentTransactionIdStatement()).map((r, md) -> r.get(0)).all();
212-
return txId.concatWith(txId);
219+
return insert.thenMany(txId.concatWith(txId));
213220
});
214221

215222
transactionIds.collectList().as(StepVerifier::create) //
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.r2dbc.function;
17+
18+
import io.r2dbc.spi.ConnectionFactory;
19+
20+
import javax.sql.DataSource;
21+
22+
import org.junit.ClassRule;
23+
import org.junit.Ignore;
24+
import org.junit.Test;
25+
26+
import org.springframework.data.r2dbc.testing.ExternalDatabase;
27+
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
28+
29+
/**
30+
* Integration tests for {@link DatabaseClient} against MySQL.
31+
*
32+
* @author Mark Paluch
33+
*/
34+
public class MySqlDatabaseClientIntegrationTests extends AbstractDatabaseClientIntegrationTests {
35+
36+
@ClassRule public static final ExternalDatabase database = MySqlTestSupport.database();
37+
38+
@Override
39+
protected DataSource createDataSource() {
40+
return MySqlTestSupport.createDataSource(database);
41+
}
42+
43+
@Override
44+
protected ConnectionFactory createConnectionFactory() {
45+
return MySqlTestSupport.createConnectionFactory(database);
46+
}
47+
48+
@Override
49+
protected String getCreateTableStatement() {
50+
return MySqlTestSupport.CREATE_TABLE_LEGOSET;
51+
}
52+
53+
@Override
54+
@Ignore("Jasync currently uses its own exceptions, see jasync-sql/jasync-sql#106")
55+
@Test
56+
public void shouldTranslateDuplicateKeyException() {}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.r2dbc.function;
17+
18+
import io.r2dbc.spi.ConnectionFactory;
19+
20+
import javax.sql.DataSource;
21+
22+
import org.junit.ClassRule;
23+
import org.junit.Ignore;
24+
import org.junit.Test;
25+
26+
import org.springframework.data.r2dbc.testing.ExternalDatabase;
27+
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
28+
29+
/**
30+
* Integration tests for {@link TransactionalDatabaseClient} against MySQL.
31+
*
32+
* @author Mark Paluch
33+
*/
34+
public class MySqlTransactionalDatabaseClientIntegrationTests
35+
extends AbstractTransactionalDatabaseClientIntegrationTests {
36+
37+
@ClassRule public static final ExternalDatabase database = MySqlTestSupport.database();
38+
39+
@Override
40+
protected DataSource createDataSource() {
41+
return MySqlTestSupport.createDataSource(database);
42+
}
43+
44+
@Override
45+
protected ConnectionFactory createConnectionFactory() {
46+
return MySqlTestSupport.createConnectionFactory(database);
47+
}
48+
49+
@Override
50+
protected String getCreateTableStatement() {
51+
return MySqlTestSupport.CREATE_TABLE_LEGOSET;
52+
}
53+
54+
@Override
55+
protected String getCurrentTransactionIdStatement() {
56+
return "SELECT tx.trx_id FROM information_schema.innodb_trx tx WHERE tx.trx_mysql_thread_id = connection_id()";
57+
}
58+
59+
@Override
60+
@Test
61+
@Ignore("MySQL creates transactions only on interaction with transactional tables. BEGIN does not create a txid")
62+
public void shouldManageUserTransaction() {}
63+
}

0 commit comments

Comments
 (0)