diff --git a/docs/modules/databases/presto.md b/docs/modules/databases/presto.md index d0a47fc1d7a..4e7ed7d081d 100644 --- a/docs/modules/databases/presto.md +++ b/docs/modules/databases/presto.md @@ -1,8 +1,5 @@ # Presto Module -!!! note - This module is deprecated, use Trino module. - See [Database containers](./index.md) for documentation and usage that is common to all database container types. ## Usage example @@ -84,6 +81,6 @@ Add the following dependency to your `pom.xml`/`build.gradle` file: !!! hint Adding this Testcontainers library JAR will not automatically add the Presto JDBC driver JAR to your project. You should ensure that your project has the Presto JDBC driver as a dependency, if you plan on using it. - Refer to [Presto project download page](https://prestosql.io/download.html) for instructions. + Refer to [Presto project download page](https://prestodb.io/getting-started/) for instructions. diff --git a/modules/presto/build.gradle b/modules/presto/build.gradle index ad35cd6ec25..afa942a8d13 100644 --- a/modules/presto/build.gradle +++ b/modules/presto/build.gradle @@ -4,6 +4,6 @@ dependencies { api project(':jdbc') testImplementation project(':jdbc-test') - testRuntimeOnly 'io.prestosql:presto-jdbc:350' + testRuntimeOnly 'com.facebook.presto:presto-jdbc:0.290' compileOnly 'org.jetbrains:annotations:24.1.0' } diff --git a/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java b/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java index 946f6a95c6d..515e2d991ce 100644 --- a/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java +++ b/modules/presto/src/main/java/org/testcontainers/containers/PrestoContainer.java @@ -2,28 +2,32 @@ import com.google.common.base.Strings; import org.jetbrains.annotations.NotNull; -import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.containers.wait.strategy.WaitAllStrategy; +import org.testcontainers.images.builder.Transferable; import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; import java.sql.Connection; import java.sql.SQLException; -import java.time.Duration; -import java.time.temporal.ChronoUnit; import java.util.Set; /** - * @deprecated Use {@code TrinoContainer} instead. + * Testcontainers implementation for Presto. + *

+ * Supported image: {@code prestodb/presto} + *

+ * Exposed ports: 8080 */ -@Deprecated public class PrestoContainer> extends JdbcDatabaseContainer { public static final String NAME = "presto"; - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("ghcr.io/trinodb/presto"); + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("prestodb/presto"); - public static final String IMAGE = "ghcr.io/trinodb/presto"; + public static final String IMAGE = "prestodb/presto"; - public static final String DEFAULT_TAG = "344"; + public static final String DEFAULT_TAG = "0.290"; public static final Integer PRESTO_PORT = 8080; @@ -46,13 +50,18 @@ public PrestoContainer(final String dockerImageName) { public PrestoContainer(final DockerImageName dockerImageName) { super(dockerImageName); dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - - this.waitStrategy = - new LogMessageWaitStrategy() - .withRegEx(".*======== SERVER STARTED ========.*") - .withStartupTimeout(Duration.of(60, ChronoUnit.SECONDS)); - + waitingFor(new WaitAllStrategy() + .withStrategy(Wait.forHttp("/v1/info/state").forPort(8080).forResponsePredicate("\"ACTIVE\""::equals)) + .withStrategy(new PrestoWaitStrategy(this))); addExposedPort(PRESTO_PORT); + withCopyFileToContainer( + MountableFile.forClasspathResource("default/catalog", Transferable.DEFAULT_DIR_MODE), + "/opt/presto-server/etc/catalog" + ); + withCopyFileToContainer( + MountableFile.forClasspathResource("default/config.properties", Transferable.DEFAULT_DIR_MODE), + "/opt/presto-server/etc/config.properties" + ); } /** @@ -68,7 +77,7 @@ protected Set getLivenessCheckPorts() { @Override public String getDriverClassName() { - return "io.prestosql.jdbc.PrestoDriver"; + return "com.facebook.presto.jdbc.PrestoDriver"; } @Override diff --git a/modules/presto/src/main/java/org/testcontainers/containers/PrestoWaitStrategy.java b/modules/presto/src/main/java/org/testcontainers/containers/PrestoWaitStrategy.java new file mode 100644 index 00000000000..a7eeedc48e1 --- /dev/null +++ b/modules/presto/src/main/java/org/testcontainers/containers/PrestoWaitStrategy.java @@ -0,0 +1,47 @@ +package org.testcontainers.containers; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.rnorth.ducttape.unreliables.Unreliables; +import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; +import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.concurrent.TimeUnit; + +/** + * Custom wait strategy for Presto. + */ +@RequiredArgsConstructor +@Slf4j +public final class PrestoWaitStrategy extends AbstractWaitStrategy { + + private final WaitStrategyTarget target; + + @SuppressWarnings("SqlNoDataSourceInspection") + @Override + public void waitUntilReady(WaitStrategyTarget target) { + PrestoContainer container = (PrestoContainer) target; + Unreliables.retryUntilSuccess( + (int) startupTimeout.getSeconds(), + TimeUnit.SECONDS, + () -> { + getRateLimiter().doWhenReady(() -> { + try (Connection con = container.createConnection(); Statement stmt = con.createStatement()) { + stmt.execute("SHOW SCHEMAS"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + return true; + } + ); + } + + @Override + public void waitUntilReady() { + waitUntilReady(target); + } +} diff --git a/modules/presto/src/main/resources/default/catalog/memory.properties b/modules/presto/src/main/resources/default/catalog/memory.properties new file mode 100644 index 00000000000..833abd3fb26 --- /dev/null +++ b/modules/presto/src/main/resources/default/catalog/memory.properties @@ -0,0 +1 @@ +connector.name=memory diff --git a/modules/presto/src/main/resources/default/catalog/tpch.properties b/modules/presto/src/main/resources/default/catalog/tpch.properties new file mode 100644 index 00000000000..75110c5acf1 --- /dev/null +++ b/modules/presto/src/main/resources/default/catalog/tpch.properties @@ -0,0 +1 @@ +connector.name=tpch diff --git a/modules/presto/src/main/resources/default/config.properties b/modules/presto/src/main/resources/default/config.properties new file mode 100644 index 00000000000..035847a4f56 --- /dev/null +++ b/modules/presto/src/main/resources/default/config.properties @@ -0,0 +1,7 @@ +coordinator=true +node-scheduler.include-coordinator=true +http-server.http.port=8080 +discovery-server.enabled=true +discovery.uri=http://localhost:8080 +offset-clause-enabled=true +cluster.required-workers-active=1 diff --git a/modules/presto/src/test/java/org/testcontainers/PrestoTestImages.java b/modules/presto/src/test/java/org/testcontainers/PrestoTestImages.java index 498e09f0be4..bcf389f08ff 100644 --- a/modules/presto/src/test/java/org/testcontainers/PrestoTestImages.java +++ b/modules/presto/src/test/java/org/testcontainers/PrestoTestImages.java @@ -3,7 +3,7 @@ import org.testcontainers.utility.DockerImageName; public interface PrestoTestImages { - DockerImageName PRESTO_TEST_IMAGE = DockerImageName.parse("ghcr.io/trinodb/presto:344"); + DockerImageName PRESTO_TEST_IMAGE = DockerImageName.parse("prestodb/presto:0.290"); - DockerImageName PRESTO_PREVIOUS_VERSION_TEST_IMAGE = DockerImageName.parse("ghcr.io/trinodb/presto:343"); + DockerImageName PRESTO_PREVIOUS_VERSION_TEST_IMAGE = DockerImageName.parse("prestodb/presto:0.290"); } diff --git a/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java b/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java index 8f2aa15f21c..03db06530bc 100644 --- a/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java +++ b/modules/presto/src/test/java/org/testcontainers/containers/PrestoContainerTest.java @@ -28,7 +28,7 @@ public void testSimple() throws Exception { assertThat(resultSet.next()).as("has result").isTrue(); assertThat(resultSet.getString("node_version")) .as("Presto version") - .isEqualTo(PrestoContainer.DEFAULT_TAG); + .startsWith(PrestoContainer.DEFAULT_TAG); assertHasCorrectExposedAndLivenessCheckPorts(prestoSql); } } @@ -48,7 +48,7 @@ public void testSpecificVersion() throws Exception { assertThat(resultSet.next()).as("has result").isTrue(); assertThat(resultSet.getString("node_version")) .as("Presto version") - .isEqualTo(PrestoTestImages.PRESTO_PREVIOUS_VERSION_TEST_IMAGE.getVersionPart()); + .startsWith(PrestoTestImages.PRESTO_PREVIOUS_VERSION_TEST_IMAGE.getVersionPart()); } } } @@ -73,15 +73,15 @@ public void testQueryMemoryAndTpch() throws SQLException { "SELECT nationkey, element " + "FROM tpch.tiny.nation " + "JOIN memory.default.table_with_array twa ON nationkey = twa.id " + - "LEFT JOIN UNNEST(my_array) a(element) ON true " + - "ORDER BY element OFFSET 1 FETCH NEXT 3 ROWS WITH TIES " + "CROSS JOIN UNNEST(my_array) a(element) " + + "ORDER BY element OFFSET 1 FETCH FIRST 3 ROWS ONLY " ) ) { List actualElements = new ArrayList<>(); while (resultSet.next()) { actualElements.add(resultSet.getInt("element")); } - assertThat(actualElements).isEqualTo(Arrays.asList(2, 4, 42, 42, 42)); + assertThat(actualElements).isEqualTo(Arrays.asList(2, 4, 42)); } } } @@ -112,8 +112,7 @@ public void testTcJdbcUri() throws Exception { ) ) { // Verify metadata with tc: JDBC connection URI - assertThat(Integer.parseInt(PrestoContainer.DEFAULT_TAG)) - .isEqualTo(connection.getMetaData().getDatabaseMajorVersion()); + assertThat(0).isEqualTo(connection.getMetaData().getDatabaseMajorVersion()); // Verify transactions with tc: JDBC connection URI assertThat(connection.getAutoCommit()).as("Is autocommit").isTrue(); @@ -128,12 +127,10 @@ public void testTcJdbcUri() throws Exception { .as("Update result") .isEqualTo(0); try ( - ResultSet resultSet = statement.executeQuery( - "SELECT sum(cast(node_version AS bigint)) AS v FROM system.runtime.nodes" - ) + ResultSet resultSet = statement.executeQuery("SELECT node_version AS v FROM system.runtime.nodes") ) { assertThat(resultSet.next()).isTrue(); - assertThat(resultSet.getString("v")).isEqualTo(PrestoContainer.DEFAULT_TAG); + assertThat(resultSet.getString("v")).startsWith(PrestoContainer.DEFAULT_TAG); assertThat(resultSet.next()).isFalse(); } connection.commit(); diff --git a/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java b/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java index 9c5dd712104..7a59b9c572f 100644 --- a/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java +++ b/modules/presto/src/test/java/org/testcontainers/jdbc/presto/PrestoJDBCDriverTest.java @@ -14,7 +14,7 @@ public class PrestoJDBCDriverTest extends AbstractJDBCDriverTest { public static Iterable data() { return Arrays.asList( new Object[][] { // - { "jdbc:tc:presto:344://hostname/", EnumSet.of(Options.PmdKnownBroken) }, + { "jdbc:tc:presto:0.290://hostname/", EnumSet.of(Options.PmdKnownBroken) }, } ); }