Skip to content

Commit f178e91

Browse files
authored
Make TimescaleDB available with JDBC syntax (#3891)
1 parent d512ca5 commit f178e91

File tree

7 files changed

+140
-1
lines changed

7 files changed

+140
-1
lines changed

docs/modules/databases/jdbc.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ Insert `tc:` after `jdbc:` as follows. Note that the hostname, port and database
3939

4040
`jdbc:tc:postgis:9.6-2.5:///databasename`
4141

42+
#### Using TimescaleDB
43+
44+
`jdbc:tc:timescaldb:2.1.0-pg13:///databasename`
45+
4246
#### Using Trino
4347

4448
`jdbc:tc:trino:352://localhost/memory/default`

modules/jdbc-test/src/main/java/org/testcontainers/jdbc/AbstractJDBCDriverTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ private void performTestForJDBCParamUsage(HikariDataSource dataSource) throws SQ
117117
String databaseQuery = "SELECT DATABASE()";
118118
// Postgres does not have Database() as a function
119119
String databaseType = ConnectionUrl.newInstance(jdbcUrl).getDatabaseType();
120-
if (databaseType.equalsIgnoreCase("postgresql") || databaseType.equalsIgnoreCase("postgis")) {
120+
if (databaseType.equalsIgnoreCase("postgresql") ||
121+
databaseType.equalsIgnoreCase("postgis") ||
122+
databaseType.equalsIgnoreCase("timescaledb")) {
121123
databaseQuery = "SELECT CURRENT_DATABASE()";
122124
}
123125

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.testcontainers.containers;
2+
3+
import org.testcontainers.jdbc.ConnectionUrl;
4+
import org.testcontainers.utility.DockerImageName;
5+
6+
/**
7+
* Factory for TimescaleDB containers, which are a special flavour of PostgreSQL.
8+
*
9+
* @see <a href="https://docs.timescale.com/latest/introduction">https://docs.timescale.com/latest/introduction</a>
10+
*/
11+
public class TimescaleDBContainerProvider extends JdbcDatabaseContainerProvider {
12+
13+
private static final String NAME = "timescaledb";
14+
private static final String DEFAULT_TAG = "2.1.0-pg11";
15+
private static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("timescale/timescaledb").asCompatibleSubstituteFor("postgres");
16+
public static final String USER_PARAM = "user";
17+
public static final String PASSWORD_PARAM = "password";
18+
19+
20+
@Override
21+
public boolean supports(String databaseType) {
22+
return databaseType.equals(NAME);
23+
}
24+
25+
@Override
26+
public JdbcDatabaseContainer newInstance() {
27+
return newInstance(DEFAULT_TAG);
28+
}
29+
30+
@Override
31+
public JdbcDatabaseContainer newInstance(String tag) {
32+
return new PostgreSQLContainer(DEFAULT_IMAGE.withTag(tag));
33+
}
34+
35+
@Override
36+
public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) {
37+
return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM);
38+
}
39+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
org.testcontainers.containers.PostgreSQLContainerProvider
22
org.testcontainers.containers.PostgisContainerProvider
3+
org.testcontainers.containers.TimescaleDBContainerProvider
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package org.testcontainers.containers;
2+
3+
import org.junit.Test;
4+
import org.testcontainers.db.AbstractContainerDatabaseTest;
5+
6+
import java.sql.ResultSet;
7+
import java.sql.SQLException;
8+
9+
import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals;
10+
import static org.rnorth.visibleassertions.VisibleAssertions.assertNotEquals;
11+
12+
public class TimescaleDBContainerTest extends AbstractContainerDatabaseTest {
13+
14+
@Test
15+
public void testSimple() throws SQLException {
16+
try (JdbcDatabaseContainer<?> postgres = new TimescaleDBContainerProvider().newInstance()) {
17+
postgres.start();
18+
19+
ResultSet resultSet = performQuery(postgres, "SELECT 1");
20+
int resultSetInt = resultSet.getInt(1);
21+
assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
22+
}
23+
}
24+
25+
@Test
26+
public void testCommandOverride() throws SQLException {
27+
try (GenericContainer<?> postgres = new TimescaleDBContainerProvider().newInstance().withCommand("postgres -c max_connections=42")) {
28+
postgres.start();
29+
30+
ResultSet resultSet = performQuery((JdbcDatabaseContainer<?>) postgres, "SELECT current_setting('max_connections')");
31+
String result = resultSet.getString(1);
32+
assertEquals("max_connections should be overriden", "42", result);
33+
}
34+
}
35+
36+
@Test
37+
public void testUnsetCommand() throws SQLException {
38+
try (GenericContainer<?> postgres = new TimescaleDBContainerProvider().newInstance().withCommand("postgres -c max_connections=42").withCommand()) {
39+
postgres.start();
40+
41+
ResultSet resultSet = performQuery((JdbcDatabaseContainer<?>) postgres, "SELECT current_setting('max_connections')");
42+
String result = resultSet.getString(1);
43+
assertNotEquals("max_connections should not be overriden", "42", result);
44+
}
45+
}
46+
47+
@Test
48+
public void testExplicitInitScript() throws SQLException {
49+
try (JdbcDatabaseContainer<?> postgres = new TimescaleDBContainerProvider().newInstance().withInitScript("somepath/init_timescaledb.sql")) {
50+
postgres.start();
51+
52+
ResultSet resultSet = performQuery(postgres, "SELECT foo FROM bar");
53+
54+
String firstColumnValue = resultSet.getString(1);
55+
assertEquals("Value from init script should equal real value", "hello world", firstColumnValue);
56+
}
57+
}
58+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.testcontainers.jdbc.timescaledb;
2+
3+
import org.junit.runner.RunWith;
4+
import org.junit.runners.Parameterized;
5+
import org.testcontainers.jdbc.AbstractJDBCDriverTest;
6+
7+
import java.util.EnumSet;
8+
9+
import static java.util.Arrays.asList;
10+
11+
@RunWith(Parameterized.class)
12+
public class TimescaleDBJDBCDriverTest extends AbstractJDBCDriverTest {
13+
14+
@Parameterized.Parameters(name = "{index} - {0}")
15+
public static Iterable<Object[]> data() {
16+
return asList(
17+
new Object[][]{
18+
{"jdbc:tc:timescaledb://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)},
19+
{"jdbc:tc:timescaledb:2.1.0-pg13://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)},
20+
});
21+
}
22+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Extend the database with TimescaleDB
2+
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
3+
4+
CREATE TABLE bar
5+
(
6+
foo VARCHAR(255),
7+
time TIMESTAMPTZ NOT NULL
8+
);
9+
10+
SELECT create_hypertable('bar', 'time');
11+
12+
INSERT INTO bar (time, foo)
13+
VALUES (CURRENT_TIMESTAMP, 'hello world');

0 commit comments

Comments
 (0)