Skip to content

Commit

Permalink
Make TimescaleDB available with JDBC syntax (#3891)
Browse files Browse the repository at this point in the history
  • Loading branch information
raynigon authored Sep 23, 2021
1 parent d512ca5 commit f178e91
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/modules/databases/jdbc.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ Insert `tc:` after `jdbc:` as follows. Note that the hostname, port and database

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

#### Using TimescaleDB

`jdbc:tc:timescaldb:2.1.0-pg13:///databasename`

#### Using Trino

`jdbc:tc:trino:352://localhost/memory/default`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ private void performTestForJDBCParamUsage(HikariDataSource dataSource) throws SQ
String databaseQuery = "SELECT DATABASE()";
// Postgres does not have Database() as a function
String databaseType = ConnectionUrl.newInstance(jdbcUrl).getDatabaseType();
if (databaseType.equalsIgnoreCase("postgresql") || databaseType.equalsIgnoreCase("postgis")) {
if (databaseType.equalsIgnoreCase("postgresql") ||
databaseType.equalsIgnoreCase("postgis") ||
databaseType.equalsIgnoreCase("timescaledb")) {
databaseQuery = "SELECT CURRENT_DATABASE()";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.testcontainers.containers;

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

/**
* Factory for TimescaleDB containers, which are a special flavour of PostgreSQL.
*
* @see <a href="https://docs.timescale.com/latest/introduction">https://docs.timescale.com/latest/introduction</a>
*/
public class TimescaleDBContainerProvider extends JdbcDatabaseContainerProvider {

private static final String NAME = "timescaledb";
private static final String DEFAULT_TAG = "2.1.0-pg11";
private static final DockerImageName DEFAULT_IMAGE = DockerImageName.parse("timescale/timescaledb").asCompatibleSubstituteFor("postgres");
public static final String USER_PARAM = "user";
public static final String PASSWORD_PARAM = "password";


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

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

@Override
public JdbcDatabaseContainer newInstance(String tag) {
return new PostgreSQLContainer(DEFAULT_IMAGE.withTag(tag));
}

@Override
public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl) {
return newInstanceFromConnectionUrl(connectionUrl, USER_PARAM, PASSWORD_PARAM);
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
org.testcontainers.containers.PostgreSQLContainerProvider
org.testcontainers.containers.PostgisContainerProvider
org.testcontainers.containers.TimescaleDBContainerProvider
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.testcontainers.containers;

import org.junit.Test;
import org.testcontainers.db.AbstractContainerDatabaseTest;

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

import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals;
import static org.rnorth.visibleassertions.VisibleAssertions.assertNotEquals;

public class TimescaleDBContainerTest extends AbstractContainerDatabaseTest {

@Test
public void testSimple() throws SQLException {
try (JdbcDatabaseContainer<?> postgres = new TimescaleDBContainerProvider().newInstance()) {
postgres.start();

ResultSet resultSet = performQuery(postgres, "SELECT 1");
int resultSetInt = resultSet.getInt(1);
assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
}
}

@Test
public void testCommandOverride() throws SQLException {
try (GenericContainer<?> postgres = new TimescaleDBContainerProvider().newInstance().withCommand("postgres -c max_connections=42")) {
postgres.start();

ResultSet resultSet = performQuery((JdbcDatabaseContainer<?>) postgres, "SELECT current_setting('max_connections')");
String result = resultSet.getString(1);
assertEquals("max_connections should be overriden", "42", result);
}
}

@Test
public void testUnsetCommand() throws SQLException {
try (GenericContainer<?> postgres = new TimescaleDBContainerProvider().newInstance().withCommand("postgres -c max_connections=42").withCommand()) {
postgres.start();

ResultSet resultSet = performQuery((JdbcDatabaseContainer<?>) postgres, "SELECT current_setting('max_connections')");
String result = resultSet.getString(1);
assertNotEquals("max_connections should not be overriden", "42", result);
}
}

@Test
public void testExplicitInitScript() throws SQLException {
try (JdbcDatabaseContainer<?> postgres = new TimescaleDBContainerProvider().newInstance().withInitScript("somepath/init_timescaledb.sql")) {
postgres.start();

ResultSet resultSet = performQuery(postgres, "SELECT foo FROM bar");

String firstColumnValue = resultSet.getString(1);
assertEquals("Value from init script should equal real value", "hello world", firstColumnValue);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.testcontainers.jdbc.timescaledb;

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

import java.util.EnumSet;

import static java.util.Arrays.asList;

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

@Parameterized.Parameters(name = "{index} - {0}")
public static Iterable<Object[]> data() {
return asList(
new Object[][]{
{"jdbc:tc:timescaledb://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)},
{"jdbc:tc:timescaledb:2.1.0-pg13://hostname/databasename?user=someuser&password=somepwd", EnumSet.of(Options.JDBCParams)},
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-- Extend the database with TimescaleDB
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;

CREATE TABLE bar
(
foo VARCHAR(255),
time TIMESTAMPTZ NOT NULL
);

SELECT create_hypertable('bar', 'time');

INSERT INTO bar (time, foo)
VALUES (CURRENT_TIMESTAMP, 'hello world');

0 comments on commit f178e91

Please sign in to comment.