Skip to content
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

Add TiDB module #5511

Merged
merged 30 commits into from Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4de91a2
[Update] Support TiDB
Icemap Jun 20, 2022
1d0d360
[Update] TiDB documents
Icemap Jun 21, 2022
5248596
Merge branch 'master' into feat-tidb
Icemap Jun 21, 2022
94232f6
Merge branch 'master' into feat-tidb
Icemap Jul 20, 2022
e36bdb0
[Update] correct author and remove deprecated annotation
Icemap Jul 20, 2022
1fb60bd
Merge branch 'feat-tidb' of github.com:Icemap/testcontainers-java int…
Icemap Jul 20, 2022
bc8307a
[Update] format TiDB code and adapt Java 17
Icemap Jul 21, 2022
d813e4e
[Delete] no used file: my.cnf
Icemap Jul 21, 2022
e987819
[Debug] rollback changed mysql meta file
Icemap Jul 21, 2022
b32059c
[Update] consistent with the other containers by using image string
Icemap Jul 21, 2022
baa25c1
[Delete] close LogManager code
Icemap Jul 21, 2022
f1bdcfe
[Rollback] adapt props for Java 17
Icemap Jul 21, 2022
c31114a
[Rollback] org.testcontainers.containers.JdbcDatabaseContainerProvider
Icemap Jul 22, 2022
84f8d0d
[Delete] r2dbc on test scope
Icemap Jul 22, 2022
6bb2086
[Delete] auto service dependencied
Icemap Jul 22, 2022
a0435ad
Merge branch 'master' into feat-tidb
Icemap Jul 27, 2022
d4e8554
Update modules/tidb/src/main/java/org/testcontainers/containers/TiDBC…
kiview Aug 4, 2022
7eb23eb
Update modules/tidb/src/main/java/org/testcontainers/containers/TiDBC…
kiview Aug 4, 2022
e4522e7
Make `NAME` and `DOCKER_IMAGE_NAME` package-protected
kiview Aug 4, 2022
eb72033
Add TiDB module to GH automation
kiview Aug 4, 2022
c6ff27d
[Update] init_mysql.sql -> init_tidb.sql
Icemap Aug 4, 2022
8f692be
Update modules/tidb/src/main/java/org/testcontainers/containers/TiDBC…
eddumelendez Aug 4, 2022
c0df0f0
Fix spotless
eddumelendez Aug 4, 2022
cc56713
Merge branch 'master' into feat-tidb
Icemap Aug 5, 2022
c16aa77
[Rename] org.testcontainers.containers -> org.testcontainers.tidb
Icemap Aug 12, 2022
bc5c9a5
Merge branch 'master' into feat-tidb
Icemap Aug 12, 2022
5d4355b
[Unit Test] static import only from classes and interfaces
Icemap Aug 12, 2022
a25384a
Merge branch 'feat-tidb' of github.com:Icemap/testcontainers-java int…
Icemap Aug 12, 2022
6f2c6a7
[Debug] import wrong package
Icemap Aug 12, 2022
680075b
[Debug] spotlessApply
Icemap Aug 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/modules/databases/jdbc.md
Expand Up @@ -51,6 +51,10 @@ Insert `tc:` after `jdbc:` as follows. Note that the hostname, port and database

`jdbc:tc:cockroach:v21.2.3:///databasename`

#### Using TiDB

`jdbc:tc:tidb:v6.1.0:///databasename`

### Using a classpath init script

Testcontainers can run an init script after the database container is started, but before your code is given a connection to it. The script must be on the classpath, and is referenced as follows:
Expand Down
25 changes: 25 additions & 0 deletions docs/modules/databases/tidb.md
@@ -0,0 +1,25 @@
# TiDB Module

See [Database containers](./index.md) for documentation and usage that is common to all relational database container types.

## Adding this module to your project dependencies

Add the following dependency to your `pom.xml`/`build.gradle` file:

=== "Gradle"
```groovy
testImplementation "org.testcontainers:tidb:{{latest_version}}"
```

=== "Maven"
```xml
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>tidb</artifactId>
<version>{{latest_version}}</version>
<scope>test</scope>
</dependency>
```

!!! hint
Adding this Testcontainers library JAR will not automatically add a database driver JAR to your project. You should ensure that your project also has a suitable database driver as a dependency.
1 change: 1 addition & 0 deletions mkdocs.yml
Expand Up @@ -63,6 +63,7 @@ nav:
- modules/databases/orientdb.md
- modules/databases/postgres.md
- modules/databases/presto.md
- modules/databases/tidb.md
- modules/databases/trino.md
- modules/azure.md
- modules/docker_compose.md
Expand Down
@@ -1 +1 @@
org.testcontainers.containers.MySQLContainerProvider
org.testcontainers.containers.TiDBContainerProvider
Icemap marked this conversation as resolved.
Show resolved Hide resolved
19 changes: 19 additions & 0 deletions modules/tidb/build.gradle
@@ -0,0 +1,19 @@
description = "Testcontainers :: JDBC :: TiDB"

dependencies {
annotationProcessor 'com.google.auto.service:auto-service:1.0.1'
compileOnly 'com.google.auto.service:auto-service:1.0.1'
Icemap marked this conversation as resolved.
Show resolved Hide resolved

api project(':jdbc')

compileOnly project(':r2dbc')
compileOnly 'dev.miku:r2dbc-mysql:0.8.2.RELEASE'
Icemap marked this conversation as resolved.
Show resolved Hide resolved

testImplementation project(':jdbc-test')
testImplementation 'mysql:mysql-connector-java:8.0.29'

testImplementation testFixtures(project(':r2dbc'))
testImplementation 'dev.miku:r2dbc-mysql:0.8.2.RELEASE'
Icemap marked this conversation as resolved.
Show resolved Hide resolved

compileOnly 'org.jetbrains:annotations:23.0.0'
}
5 changes: 5 additions & 0 deletions modules/tidb/sql/init_mysql.sql
@@ -0,0 +1,5 @@
CREATE TABLE bar (
foo VARCHAR(255)
);

INSERT INTO bar (foo) VALUES ('hello world');
@@ -0,0 +1,146 @@
package org.testcontainers.containers;
Icemap marked this conversation as resolved.
Show resolved Hide resolved

import org.jetbrains.annotations.NotNull;
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
import org.testcontainers.utility.DockerImageName;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;

/**
* @author richardnorth
Icemap marked this conversation as resolved.
Show resolved Hide resolved
*/
public class TiDBContainer extends JdbcDatabaseContainer<TiDBContainer> {

public static final String NAME = "tidb";

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("pingcap/tidb");

@Deprecated
public static final String DEFAULT_TAG = "v6.1.0";

@Deprecated
public static final String IMAGE = DEFAULT_IMAGE_NAME.getUnversionedPart();

public static final String IMAGE_TAG = DEFAULT_TAG;

public static final Integer TIDB_PORT = 4000;
kiview marked this conversation as resolved.
Show resolved Hide resolved

private static final int REST_API_PORT = 10080;

private String databaseName = "test";

private String username = "root";

private String password = "";

/**
* @deprecated use {@link TiDBContainer (DockerImageName)} instead
*/
@Deprecated
Icemap marked this conversation as resolved.
Show resolved Hide resolved
public TiDBContainer() {
this(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG));
}

public TiDBContainer(String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
}

public TiDBContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);

addExposedPorts(TIDB_PORT, REST_API_PORT);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both ports should be exposed? or only 4000?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both ports should be exposed. TIDB_PORT is 4000, and REST_API_PORT is 10080.


waitingFor(
new HttpWaitStrategy()
.forPath("/status")
.forPort(REST_API_PORT)
.forStatusCode(200)
.withStartupTimeout(Duration.ofMinutes(1))
);
}

@NotNull
@Override
protected Set<Integer> getLivenessCheckPorts() {
return new HashSet<>(getMappedPort(TIDB_PORT));
}

@Override
public String getDriverClassName() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return "com.mysql.cj.jdbc.Driver";
} catch (ClassNotFoundException e) {
return "com.mysql.jdbc.Driver";
}
}

@Override
public String getJdbcUrl() {
String additionalUrlParams = constructUrlParameters("?", "&");
return "jdbc:mysql://" + getHost() + ":" + getMappedPort(TIDB_PORT) + "/" + databaseName + additionalUrlParams;
}

@Override
protected String constructUrlForConnection(String queryString) {
String url = super.constructUrlForConnection(queryString);

if (!url.contains("useSSL=")) {
String separator = url.contains("?") ? "&" : "?";
url = url + separator + "useSSL=false";
}

if (!url.contains("allowPublicKeyRetrieval=")) {
url = url + "&allowPublicKeyRetrieval=true";
}

return url;
}

@Override
public String getDatabaseName() {
return databaseName;
}

@Override
public String getUsername() {
return username;
}

@Override
public String getPassword() {
return password;
}

@Override
public String getTestQueryString() {
return "SELECT 1";
}

@Override
public TiDBContainer withDatabaseName(final String databaseName) {
throw new UnsupportedOperationException(
"The TiDB docker image does not currently support this"
);
}

@Override
public TiDBContainer withUsername(final String username) {
throw new UnsupportedOperationException(
"The TiDB docker image does not currently support this"
);
}

@Override
public TiDBContainer withPassword(final String password) {
throw new UnsupportedOperationException(
"The TiDB docker image does not currently support this"
);
}
}
@@ -0,0 +1,33 @@
package org.testcontainers.containers;

import org.testcontainers.jdbc.ConnectionUrl;
import org.testcontainers.utility.DockerImageName;

/**
* Factory for TiDB containers.
*/
public class TiDBContainerProvider extends JdbcDatabaseContainerProvider {

private static final String USER_PARAM = "root";

private static final String PASSWORD_PARAM = "";

@Override
public boolean supports(String databaseType) {
return databaseType.equals(TiDBContainer.NAME);
}

@Override
public JdbcDatabaseContainer newInstance() {
return newInstance(TiDBContainer.DEFAULT_TAG);
}

@Override
public JdbcDatabaseContainer newInstance(String tag) {
if (tag != null) {
return new TiDBContainer(DockerImageName.parse(TiDBContainer.IMAGE).withTag(tag));
} else {
return newInstance();
}
}
}
@@ -0,0 +1 @@
org.testcontainers.containers.TiDBContainerProvider
49 changes: 49 additions & 0 deletions modules/tidb/src/main/resources/mysql-default-conf/my.cnf
@@ -0,0 +1,49 @@
[mysqld]
Icemap marked this conversation as resolved.
Show resolved Hide resolved
user = mysql
datadir = /var/lib/mysql
port = 3306
#socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16K
max_allowed_packet = 1M
table_open_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
skip-host-cache
skip-name-resolve

# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (using the "enable-named-pipe" option) will render mysqld useless!
#
#skip-networking
#server-id = 1

# Uncomment the following if you want to log updates
#log-bin=mysql-bin

# binary logging format - mixed recommended
#binlog_format=mixed

# Causes updates to non-transactional engines using statement format to be
# written directly to binary log. Before using this option make sure that
# there are no dependencies between transactional and non-transactional
# tables such as in the statement INSERT INTO t_myisam SELECT * FROM
# t_innodb; otherwise, slaves may diverge from the master.
#binlog_direct_non_transactional_updates=TRUE

# Uncomment the following if you are using InnoDB tables
innodb_data_file_path = ibdata1:10M:autoextend
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 16M
#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
@@ -0,0 +1,8 @@
package org.testcontainers;

import org.testcontainers.utility.DockerImageName;

public class TiDBTestImages {

public static final DockerImageName TIDB_IMAGE = DockerImageName.parse("pingcap/tidb:v6.1.0");
}
@@ -0,0 +1,21 @@
package org.testcontainers.jdbc.tidb;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.testcontainers.jdbc.AbstractJDBCDriverTest;

import java.util.Arrays;
import java.util.EnumSet;

@RunWith(Parameterized.class)
public class TiDBJDBCDriverTest extends AbstractJDBCDriverTest {

@Parameterized.Parameters(name = "{index} - {0}")
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[][] {
{ "jdbc:tc:tidb://hostname/databasename", EnumSet.noneOf(Options.class) },
}
);
}
}