Skip to content

Commit

Permalink
add oceanbase-ce module
Browse files Browse the repository at this point in the history
  • Loading branch information
whhe committed Sep 19, 2023
1 parent 1c8f392 commit cc870c9
Show file tree
Hide file tree
Showing 17 changed files with 328 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ body:
- MySQL
- Neo4j
- NGINX
- OceanBase-CE
- Oracle-XE
- OrientDB
- PostgreSQL
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/enhancement.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ body:
- MySQL
- Neo4j
- NGINX
- OceanBase-CE
- Oracle-XE
- OrientDB
- PostgreSQL
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ body:
- MySQL
- Neo4j
- NGINX
- OceanBase-CE
- Oracle-XE
- OrientDB
- PostgreSQL
Expand Down
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ updates:
schedule:
interval: "monthly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/oceanbase-ce"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/oracle-xe"
schedule:
Expand Down
2 changes: 2 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
- modules/neo4j/**/*
"modules/nginx":
- modules/nginx/**/*
"modules/oceanbase-ce":
- modules/oceanbase-ce/**/*
"modules/oracle":
- modules/oracle-xe/**/*
"modules/orientdb":
Expand Down
4 changes: 4 additions & 0 deletions docs/modules/databases/jdbc.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ Insert `tc:` after `jdbc:` as follows. Note that the hostname, port and database

`jdbc:tc:sqlserver:2017-CU12:///databasename`

#### Using OceanBase

`jdbc:tc:oceanbase:4.1.0.0:///databasename`

#### Using Oracle

`jdbc:tc:oracle:21-slim-faststart:///databasename`
Expand Down
25 changes: 25 additions & 0 deletions docs/modules/databases/oceanbasece.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# OceanBase-CE 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:oceanbase-ce:{{latest_version}}"
```

=== "Maven"
```xml
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>oceanbase-ce</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
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ nav:
- modules/databases/mssqlserver.md
- modules/databases/mysql.md
- modules/databases/neo4j.md
- modules/databases/oceanbasece.md
- modules/databases/oraclexe.md
- modules/databases/orientdb.md
- modules/databases/postgres.md
Expand Down
10 changes: 10 additions & 0 deletions modules/oceanbase-ce/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
description = "Testcontainers :: JDBC :: OceanBase"

dependencies {
api project(':jdbc')

testImplementation project(':jdbc-test')
testRuntimeOnly 'com.oceanbase:oceanbase-client:2.4.3'

compileOnly 'org.jetbrains:annotations:24.0.1'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.testcontainers.containers;

import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.utility.DockerImageName;

import java.time.Duration;

/**
* Testcontainers implementation for OceanBase.
* <p>
* Supported image: {@code oceanbase/oceanbase-ce}
* <p>
* Exposed ports:
* <ul>
* <li>SQL: 2881</li>
* <li>RPC: 2882</li>
* </ul>
*/
public class OceanBaseContainer extends JdbcDatabaseContainer<OceanBaseContainer> {

static final String NAME = "oceanbase";

static final String DOCKER_IMAGE_NAME = "oceanbase/oceanbase-ce";

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse(DOCKER_IMAGE_NAME);

private static final Integer SQL_PORT = 2881;

private static final Integer RPC_PORT = 2882;

private final String databaseName = "test";
private final String username = "root@test";
private final String password = "";

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

public OceanBaseContainer(DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);

this.waitStrategy = Wait.forLogMessage(".*boot success!.*", 1).withStartupTimeout(Duration.ofMinutes(3));

addExposedPorts(SQL_PORT, RPC_PORT);
}

public Integer getSqlPort() {
return getMappedPort(SQL_PORT);
}

public Integer getRpcPort() {
return getMappedPort(RPC_PORT);
}

@Override
public String getDriverClassName() {
return "com.oceanbase.jdbc.Driver";
}

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

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

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

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

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

@Override
protected void waitUntilContainerStarted() {
getWaitStrategy().waitUntilReady(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.testcontainers.containers;

import org.testcontainers.utility.DockerImageName;

/**
* Factory for OceanBase containers.
*/
public class OceanBaseContainerProvider extends JdbcDatabaseContainerProvider {

private static final String DEFAULT_TAG = "4.1.0.0";

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

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

@Override
public JdbcDatabaseContainer newInstance(String tag) {
if (tag != null) {
return new OceanBaseContainer(DockerImageName.parse(OceanBaseContainer.DOCKER_IMAGE_NAME).withTag(tag));
} else {
return newInstance();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.testcontainers.containers.OceanBaseContainerProvider
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.testcontainers;

import org.testcontainers.utility.DockerImageName;

public class OceanBaseTestImages {

public static final DockerImageName OCEANBASE_CE_IMAGE = DockerImageName.parse("oceanbase/oceanbase-ce:4.1.0.0");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.testcontainers.jdbc.oceanbase;

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 OceanBaseJdbcDriverTest extends AbstractJDBCDriverTest {

@Parameterized.Parameters(name = "{index} - {0}")
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[][] { { "jdbc:tc:oceanbase://hostname/databasename", EnumSet.noneOf(Options.class) } }
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.testcontainers.junit.oceanbase;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.OceanBaseTestImages;
import org.testcontainers.containers.OceanBaseContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.db.AbstractContainerDatabaseTest;

import java.sql.ResultSet;
import java.sql.SQLException;

import static org.assertj.core.api.Assertions.assertThat;

public class SimpleOceanBaseTest extends AbstractContainerDatabaseTest {

private static final Logger logger = LoggerFactory.getLogger(SimpleOceanBaseTest.class);

@Test
public void testSimple() throws SQLException {
try (
OceanBaseContainer container = new OceanBaseContainer(OceanBaseTestImages.OCEANBASE_CE_IMAGE)
.withLogConsumer(new Slf4jLogConsumer(logger))
) {
container.start();

ResultSet resultSet = performQuery(container, "SELECT 1");
int resultSetInt = resultSet.getInt(1);

assertThat(resultSetInt).as("A basic SELECT query succeeds").isEqualTo(1);
}
}

@Test
public void testExplicitInitScript() throws SQLException {
try (
OceanBaseContainer container = new OceanBaseContainer(OceanBaseTestImages.OCEANBASE_CE_IMAGE)
.withInitScript("init.sql")
.withLogConsumer(new Slf4jLogConsumer(logger))
) {
container.start();

ResultSet resultSet = performQuery(container, "SELECT foo FROM bar");
String firstColumnValue = resultSet.getString(1);

assertThat(firstColumnValue).as("Value from init script should equal real value").isEqualTo("hello world");
}
}

@Test
public void testWithAdditionalUrlParamInJdbcUrl() {
try (
OceanBaseContainer container = new OceanBaseContainer(OceanBaseTestImages.OCEANBASE_CE_IMAGE)
.withUrlParam("useSSL", "false")
.withLogConsumer(new Slf4jLogConsumer(logger))
) {
container.start();

container.start();
String jdbcUrl = container.getJdbcUrl();
assertThat(jdbcUrl).contains("?");
assertThat(jdbcUrl).contains("useSSL=false");
}
}
}
45 changes: 45 additions & 0 deletions modules/oceanbase-ce/src/test/resources/init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
CREATE TABLE bar (
foo VARCHAR(255)
);

DROP PROCEDURE IF EXISTS -- ;
count_foo;

SELECT "a /* string literal containing comment characters like -- here";
SELECT "a 'quoting' \"scenario ` involving BEGIN keyword\" here";
SELECT * from `bar`;
-- What about a line comment containing imbalanced string delimiters? "
CREATE PROCEDURE count_foo()
BEGIN
BEGIN
SELECT *
FROM bar;
SELECT 1
FROM dual;
END;
BEGIN
select * from bar;
END;
-- we can do comments
/* including block
comments
*/
/* what if BEGIN appears inside a comment? */
select "or what if BEGIN appears inside a literal?";
END /*; */;
/* or a block comment
containing imbalanced string delimiters?
' "
*/
INSERT INTO bar (foo) /* ; */ VALUES ('hello world');
16 changes: 16 additions & 0 deletions modules/oceanbase-ce/src/test/resources/logback-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>

<logger name="org.testcontainers" level="INFO"/>
</configuration>

0 comments on commit cc870c9

Please sign in to comment.