diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5fab70899c9..324bef4791bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -449,6 +449,7 @@ jobs: !:trino-accumulo, !:trino-bigquery, !:trino-cassandra, + !:trino-scylla, !:trino-clickhouse, !:trino-delta-lake, !:trino-docs,!:trino-server,!:trino-server-rpm, @@ -554,6 +555,7 @@ jobs: - { modules: plugin/trino-bigquery } - { modules: plugin/trino-bigquery, profile: cloud-tests-arrow } - { modules: plugin/trino-cassandra } + - { modules: plugin/trino-scylla } - { modules: plugin/trino-clickhouse } - { modules: plugin/trino-delta-lake } - { modules: plugin/trino-delta-lake, profile: cloud-tests } @@ -983,6 +985,9 @@ jobs: - config: default suite: suite-cassandra # this suite is not meant to be run with different configs + - config: default + suite: suite-scylla + # this suite is not meant to be run with different configs - config: default suite: suite-clickhouse # this suite is not meant to be run with different configs diff --git a/core/trino-server/src/main/provisio/trino.xml b/core/trino-server/src/main/provisio/trino.xml index 8e014d0b9a57..c747cf584498 100644 --- a/core/trino-server/src/main/provisio/trino.xml +++ b/core/trino-server/src/main/provisio/trino.xml @@ -306,4 +306,10 @@ + + + + + + diff --git a/docs/src/main/sphinx/connector.md b/docs/src/main/sphinx/connector.md index 3b86e28f3d56..1ada1a9e7d60 100644 --- a/docs/src/main/sphinx/connector.md +++ b/docs/src/main/sphinx/connector.md @@ -36,6 +36,7 @@ PostgreSQL Prometheus Redis Redshift +Scylla SingleStore SQL Server System diff --git a/docs/src/main/sphinx/connector/scylla.rst b/docs/src/main/sphinx/connector/scylla.rst new file mode 100644 index 000000000000..d3b0498a8ead --- /dev/null +++ b/docs/src/main/sphinx/connector/scylla.rst @@ -0,0 +1,38 @@ +================ +Scylla connector +================ + +The Scylla connector allows querying data stored in +`Scylla `_. + +Requirements +------------ + +To connect to Scylla, you need: + +* Scylla version 3.0.0 or higher. +* Network access from the Trino coordinator and workers to Scylla. + Port 9042 is the default port. + +Configuration +------------- + +To configure the Scylla connector, create a catalog properties file +``etc/catalog/example.properties`` with the following contents, +replacing ``host1,host2`` with a comma-separated list of the Scylla +nodes, used to discovery the cluster topology: + +.. code-block:: text + + connector.name=scylla + cassandra.contact-points=host1,host2 + +You also need to set ``cassandra.native-protocol-port``, if your +Scylla nodes are not using the default port 9042. + +Compatibility with Cassandra connector +-------------------------------------- + +The Scylla connector is very similar to the Cassandra connector with the +only difference being the underlying driver. +See :doc:`Cassandra connector ` for more details. diff --git a/plugin/trino-scylla/pom.xml b/plugin/trino-scylla/pom.xml new file mode 100644 index 000000000000..cd217ad90109 --- /dev/null +++ b/plugin/trino-scylla/pom.xml @@ -0,0 +1,192 @@ + + + 4.0.0 + + + io.trino + trino-root + 423-SNAPSHOT + ../../pom.xml + + + trino-scylla + trino-plugin + Trino - Scylla Connector + + + ${project.parent.basedir} + + + + + com.google.guava + guava + + + + io.trino + trino-cassandra + ${project.version} + + + com.datastax.oss + java-driver-core + + + + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + + io.airlift + slice + provided + + + + io.opentelemetry + opentelemetry-api + provided + + + + io.opentelemetry + opentelemetry-context + provided + + + + io.trino + trino-spi + provided + + + + org.openjdk.jol + jol-core + provided + + + + com.scylladb + java-driver-core + 4.13.0.0 + runtime + + + + io.airlift + json + runtime + + + + io.airlift + log + runtime + + + + io.airlift + log-manager + runtime + + + + io.airlift + units + runtime + + + + io.airlift + testing + test + + + + + io.trino + trino-cassandra + ${project.version} + test-jar + test + + + + io.trino + trino-main + test-jar + test + + + + io.trino + trino-main + test + + + + io.trino + trino-testing + test + + + + io.trino + trino-tpch + test + + + + io.trino.tpch + tpch + test + + + + org.apache.thrift + libthrift + test + + + + org.assertj + assertj-core + test + + + + org.testcontainers + testcontainers + test + + + + org.testng + testng + test + + + + + + + org.basepom.maven + duplicate-finder-maven-plugin + + + + com.datastax.oss + java-driver-core + + + + + + + diff --git a/plugin/trino-scylla/src/main/java/io/trino/plugin/scylla/ScyllaConnectorFactory.java b/plugin/trino-scylla/src/main/java/io/trino/plugin/scylla/ScyllaConnectorFactory.java new file mode 100644 index 000000000000..9260ca48e65b --- /dev/null +++ b/plugin/trino-scylla/src/main/java/io/trino/plugin/scylla/ScyllaConnectorFactory.java @@ -0,0 +1,26 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.plugin.scylla; + +import io.trino.plugin.cassandra.CassandraConnectorFactory; + +public class ScyllaConnectorFactory + extends CassandraConnectorFactory +{ + @Override + public String getName() + { + return "scylla"; + } +} diff --git a/plugin/trino-scylla/src/main/java/io/trino/plugin/scylla/ScyllaPlugin.java b/plugin/trino-scylla/src/main/java/io/trino/plugin/scylla/ScyllaPlugin.java new file mode 100644 index 000000000000..6c9b549123ca --- /dev/null +++ b/plugin/trino-scylla/src/main/java/io/trino/plugin/scylla/ScyllaPlugin.java @@ -0,0 +1,28 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.plugin.scylla; + +import com.google.common.collect.ImmutableList; +import io.trino.spi.Plugin; +import io.trino.spi.connector.ConnectorFactory; + +public class ScyllaPlugin + implements Plugin +{ + @Override + public Iterable getConnectorFactories() + { + return ImmutableList.of(new ScyllaConnectorFactory()); + } +} diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/ScyllaQueryRunner.java b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/ScyllaQueryRunner.java similarity index 92% rename from plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/ScyllaQueryRunner.java rename to plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/ScyllaQueryRunner.java index 52de69544c78..81e63d75c47e 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/ScyllaQueryRunner.java +++ b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/ScyllaQueryRunner.java @@ -11,12 +11,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.trino.plugin.cassandra; +package io.trino.plugin.scylla; import com.google.common.collect.ImmutableMap; import io.airlift.log.Logger; import io.airlift.log.Logging; import io.trino.Session; +import io.trino.plugin.cassandra.CassandraServer; import io.trino.plugin.tpch.TpchPlugin; import io.trino.testing.DistributedQueryRunner; import io.trino.tpch.TpchTable; @@ -35,7 +36,7 @@ public final class ScyllaQueryRunner private ScyllaQueryRunner() {} public static DistributedQueryRunner createScyllaQueryRunner( - TestingScyllaServer server, + CassandraServer server, Map extraProperties, Map connectorProperties, Iterable> tables) @@ -57,8 +58,8 @@ public static DistributedQueryRunner createScyllaQueryRunner( connectorProperties.putIfAbsent("cassandra.load-policy.use-dc-aware", "true"); connectorProperties.putIfAbsent("cassandra.load-policy.dc-aware.local-dc", "datacenter1"); - queryRunner.installPlugin(new CassandraPlugin()); - queryRunner.createCatalog("cassandra", "cassandra", connectorProperties); + queryRunner.installPlugin(new ScyllaPlugin()); + queryRunner.createCatalog("scylla", "scylla", connectorProperties); createKeyspace(server.getSession(), "tpch"); copyTpchTables(queryRunner, "tpch", TINY_SCHEMA_NAME, createSession("tpch"), tables); @@ -76,7 +77,7 @@ public static DistributedQueryRunner createScyllaQueryRunner( public static Session createSession(String schema) { return testSessionBuilder() - .setCatalog("cassandra") + .setCatalog("scylla") .setSchema(schema) .build(); } diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestScyllaConnectorSmokeTest.java b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaConnectorSmokeTest.java similarity index 80% rename from plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestScyllaConnectorSmokeTest.java rename to plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaConnectorSmokeTest.java index 3c9c992d1100..8d29cff27edd 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestScyllaConnectorSmokeTest.java +++ b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaConnectorSmokeTest.java @@ -11,15 +11,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.trino.plugin.cassandra; +package io.trino.plugin.scylla; import com.google.common.collect.ImmutableMap; +import io.trino.plugin.cassandra.BaseCassandraConnectorSmokeTest; +import io.trino.plugin.cassandra.CassandraSession; import io.trino.testing.QueryRunner; import java.sql.Timestamp; import static io.trino.plugin.cassandra.CassandraTestingUtils.createTestTables; -import static io.trino.plugin.cassandra.ScyllaQueryRunner.createScyllaQueryRunner; +import static io.trino.plugin.scylla.ScyllaQueryRunner.createScyllaQueryRunner; +import static io.trino.plugin.scylla.TestingScyllaServer.V3_TAG; public class TestScyllaConnectorSmokeTest extends BaseCassandraConnectorSmokeTest @@ -28,7 +31,7 @@ public class TestScyllaConnectorSmokeTest protected QueryRunner createQueryRunner() throws Exception { - TestingScyllaServer server = closeAfterClass(new TestingScyllaServer("3.3.4")); + TestingScyllaServer server = closeAfterClass(new TestingScyllaServer(V3_TAG)); CassandraSession session = server.getSession(); createTestTables(session, KEYSPACE, Timestamp.from(TIMESTAMP_VALUE.toInstant())); return createScyllaQueryRunner(server, ImmutableMap.of(), ImmutableMap.of(), REQUIRED_TPCH_TABLES); diff --git a/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaConnectorTest.java b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaConnectorTest.java new file mode 100644 index 000000000000..6b31f8674bed --- /dev/null +++ b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaConnectorTest.java @@ -0,0 +1,42 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.plugin.scylla; + +import com.google.common.collect.ImmutableMap; +import io.trino.plugin.cassandra.BaseCassandraConnectorTest; +import io.trino.testing.QueryRunner; + +import java.sql.Timestamp; + +import static io.trino.plugin.cassandra.CassandraTestingUtils.createTestTables; +import static io.trino.plugin.scylla.ScyllaQueryRunner.createScyllaQueryRunner; +import static io.trino.plugin.scylla.TestingScyllaServer.V3_TAG; + +public class TestScyllaConnectorTest + extends BaseCassandraConnectorTest +{ + @Override + protected QueryRunner createQueryRunner() + throws Exception + { + server = closeAfterClass(new TestingScyllaServer(V3_TAG)); + session = server.getSession(); + createTestTables(session, KEYSPACE, Timestamp.from(TIMESTAMP_VALUE.toInstant())); + return createScyllaQueryRunner( + server, + ImmutableMap.of(), + ImmutableMap.of("cassandra.batch-size", "50"), // The default 100 causes 'Batch too large' error + REQUIRED_TPCH_TABLES); + } +} diff --git a/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaLatestConnectorSmokeTest.java b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaLatestConnectorSmokeTest.java new file mode 100644 index 000000000000..a714b8d6fa98 --- /dev/null +++ b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestScyllaLatestConnectorSmokeTest.java @@ -0,0 +1,39 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.plugin.scylla; + +import com.google.common.collect.ImmutableMap; +import io.trino.plugin.cassandra.BaseCassandraConnectorSmokeTest; +import io.trino.plugin.cassandra.CassandraSession; +import io.trino.testing.QueryRunner; + +import java.sql.Timestamp; + +import static io.trino.plugin.cassandra.CassandraTestingUtils.createTestTables; +import static io.trino.plugin.scylla.ScyllaQueryRunner.createScyllaQueryRunner; +import static io.trino.plugin.scylla.TestingScyllaServer.V4_TAG; + +public class TestScyllaLatestConnectorSmokeTest + extends BaseCassandraConnectorSmokeTest +{ + @Override + protected QueryRunner createQueryRunner() + throws Exception + { + TestingScyllaServer server = closeAfterClass(new TestingScyllaServer(V4_TAG)); + CassandraSession session = server.getSession(); + createTestTables(session, KEYSPACE, Timestamp.from(TIMESTAMP_VALUE.toInstant())); + return createScyllaQueryRunner(server, ImmutableMap.of(), ImmutableMap.of(), REQUIRED_TPCH_TABLES); + } +} diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestingScyllaServer.java b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestingScyllaServer.java similarity index 92% rename from plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestingScyllaServer.java rename to plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestingScyllaServer.java index 5888408b06d5..dcdd7977aede 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestingScyllaServer.java +++ b/plugin/trino-scylla/src/test/java/io/trino/plugin/scylla/TestingScyllaServer.java @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.trino.plugin.cassandra; +package io.trino.plugin.scylla; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.CqlSessionBuilder; @@ -21,9 +21,12 @@ import io.airlift.json.JsonCodec; import io.airlift.log.Logger; import io.airlift.units.Duration; +import io.trino.plugin.cassandra.CassandraServer; +import io.trino.plugin.cassandra.CassandraSession; +import io.trino.plugin.cassandra.ExtraColumnMetadata; +import io.trino.plugin.cassandra.SizeEstimate; import org.testcontainers.containers.GenericContainer; -import java.io.Closeable; import java.net.InetSocketAddress; import java.util.List; import java.util.concurrent.TimeoutException; @@ -40,12 +43,14 @@ import static java.util.concurrent.TimeUnit.SECONDS; public class TestingScyllaServer - implements Closeable + implements CassandraServer { private static final Logger log = Logger.get(TestingScyllaServer.class); - private static final int PORT = 9042; + public static final String V4_TAG = "4.5.3"; + public static final String V3_TAG = "3.0.0"; + private static final int PORT = 9042; private static final Duration REFRESH_SIZE_ESTIMATES_TIMEOUT = new Duration(1, MINUTES); private final GenericContainer container; @@ -53,7 +58,7 @@ public class TestingScyllaServer public TestingScyllaServer() { - this("2.2.0"); + this(V3_TAG); } public TestingScyllaServer(String version) @@ -83,21 +88,25 @@ public TestingScyllaServer(String version) new Duration(1, MINUTES)); } + @Override public CassandraSession getSession() { return requireNonNull(session, "session is null"); } + @Override public String getHost() { return container.getHost(); } + @Override public int getPort() { return container.getMappedPort(PORT); } + @Override public void refreshSizeEstimates(String keyspace, String table) throws Exception { diff --git a/pom.xml b/pom.xml index a9662c95012f..1a419636545c 100644 --- a/pom.xml +++ b/pom.xml @@ -100,6 +100,7 @@ plugin/trino-redis plugin/trino-redshift plugin/trino-resource-group-managers + plugin/trino-scylla plugin/trino-session-property-managers plugin/trino-singlestore plugin/trino-sqlserver diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvMultinodeAllConnectors.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvMultinodeAllConnectors.java index 0ba9cf6edd05..91e71489f803 100644 --- a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvMultinodeAllConnectors.java +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvMultinodeAllConnectors.java @@ -77,6 +77,7 @@ public void extendEnvironment(Environment.Builder builder) "raptor_legacy", "redis", "redshift", + "scylla", "sqlserver", "trino_thrift", "tpcds") diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvMultinodeScylla.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvMultinodeScylla.java new file mode 100644 index 000000000000..61d85450126a --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/env/environment/EnvMultinodeScylla.java @@ -0,0 +1,74 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.tests.product.launcher.env.environment; + +import com.google.inject.Inject; +import io.trino.tests.product.launcher.docker.DockerFiles; +import io.trino.tests.product.launcher.docker.DockerFiles.ResourceProvider; +import io.trino.tests.product.launcher.env.DockerContainer; +import io.trino.tests.product.launcher.env.Environment.Builder; +import io.trino.tests.product.launcher.env.EnvironmentProvider; +import io.trino.tests.product.launcher.env.common.StandardMultinode; +import io.trino.tests.product.launcher.env.common.TestsEnvironment; +import io.trino.tests.product.launcher.testcontainers.PortBinder; +import org.testcontainers.containers.startupcheck.IsRunningStartupCheckStrategy; + +import java.time.Duration; + +import static io.trino.tests.product.launcher.docker.ContainerUtil.forSelectedPorts; +import static io.trino.tests.product.launcher.env.EnvironmentContainers.configureTempto; +import static java.util.Objects.requireNonNull; +import static org.testcontainers.utility.MountableFile.forHostPath; + +@TestsEnvironment +public class EnvMultinodeScylla + extends EnvironmentProvider +{ + public static final int SCYLLA_PORT = 9042; + + private final ResourceProvider configDir; + private final PortBinder portBinder; + + @Inject + public EnvMultinodeScylla(StandardMultinode standardMultinode, DockerFiles dockerFiles, PortBinder portBinder) + { + super(standardMultinode); + this.configDir = requireNonNull(dockerFiles, "dockerFiles is null").getDockerFilesHostDirectory("conf/environment/multinode-scylla/"); + this.portBinder = requireNonNull(portBinder, "portBinder is null"); + } + + @Override + public void extendEnvironment(Builder builder) + { + builder.addConnector("scylla", forHostPath(configDir.getPath("scylla.properties"))); + builder.addContainer(createScylla()); + configureTempto(builder, configDir); + } + + private DockerContainer createScylla() + { + DockerContainer container = new DockerContainer("scylladb/scylla:4.6.2", "scylla") + .withEnv("HEAP_NEWSIZE", "128M") + .withEnv("MAX_HEAP_SIZE", "512M") + // Limit SMP to run in a machine having many cores https://github.com/scylladb/scylla/issues/5638 + .withCommand("--smp", "1") + .withStartupCheckStrategy(new IsRunningStartupCheckStrategy()) + .waitingFor(forSelectedPorts(SCYLLA_PORT)) + .withStartupTimeout(Duration.ofMinutes(5)); + + portBinder.exposePort(container, SCYLLA_PORT); + + return container; + } +} diff --git a/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/suite/suites/SuiteScylla.java b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/suite/suites/SuiteScylla.java new file mode 100644 index 000000000000..87eddd7d0a60 --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/java/io/trino/tests/product/launcher/suite/suites/SuiteScylla.java @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.tests.product.launcher.suite.suites; + +import com.google.common.collect.ImmutableList; +import io.trino.tests.product.launcher.env.EnvironmentConfig; +import io.trino.tests.product.launcher.env.environment.EnvMultinodeScylla; +import io.trino.tests.product.launcher.suite.Suite; +import io.trino.tests.product.launcher.suite.SuiteTestRun; + +import java.util.List; + +import static io.trino.tests.product.launcher.suite.SuiteTestRun.testOnEnvironment; + +public class SuiteScylla + extends Suite +{ + @Override + public List getTestRuns(EnvironmentConfig config) + { + return ImmutableList.of( + testOnEnvironment(EnvMultinodeScylla.class) + .withGroups("configured_features", "scylla") + .build()); + } +} diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-all/scylla.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-all/scylla.properties new file mode 100644 index 000000000000..48d4ab86786e --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-all/scylla.properties @@ -0,0 +1,3 @@ +connector.name=scylla +cassandra.contact-points=host1.invalid,host2.invalid +cassandra.load-policy.dc-aware.local-dc=datacenter1 diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-scylla/scylla.properties b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-scylla/scylla.properties new file mode 100644 index 000000000000..883f48a5452b --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-scylla/scylla.properties @@ -0,0 +1,5 @@ +connector.name=scylla +cassandra.contact-points=scylla +cassandra.allow-drop-table=true +cassandra.load-policy.use-dc-aware=true +cassandra.load-policy.dc-aware.local-dc=datacenter1 diff --git a/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-scylla/tempto-configuration.yaml b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-scylla/tempto-configuration.yaml new file mode 100644 index 000000000000..cefae6c56579 --- /dev/null +++ b/testing/trino-product-tests-launcher/src/main/resources/docker/presto-product-tests/conf/environment/multinode-scylla/tempto-configuration.yaml @@ -0,0 +1,3 @@ +databases: + presto: + jdbc_url: "jdbc:trino://${databases.presto.host}:${databases.presto.port}/scylla/test" diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestGroups.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestGroups.java index 9bb8110f04a1..802e8960d396 100644 --- a/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestGroups.java +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/TestGroups.java @@ -58,6 +58,7 @@ public final class TestGroups public static final String HIVE_COERCION = "hive_coercion"; public static final String AZURE = "azure"; public static final String CASSANDRA = "cassandra"; + public static final String SCYLLA = "scylla"; public static final String SQL_SERVER = "sqlserver"; public static final String LDAP = "ldap"; public static final String LDAP_AND_FILE = "ldap_and_file"; diff --git a/testing/trino-product-tests/src/main/java/io/trino/tests/product/scylla/TestScylla.java b/testing/trino-product-tests/src/main/java/io/trino/tests/product/scylla/TestScylla.java new file mode 100644 index 000000000000..99c9bd45f970 --- /dev/null +++ b/testing/trino-product-tests/src/main/java/io/trino/tests/product/scylla/TestScylla.java @@ -0,0 +1,70 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.trino.tests.product.scylla; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.google.inject.Inject; +import io.trino.tempto.BeforeMethodWithContext; +import io.trino.tempto.ProductTest; +import io.trino.tempto.configuration.Configuration; +import io.trino.tempto.query.QueryResult; +import org.intellij.lang.annotations.Language; +import org.testng.annotations.Test; + +import java.net.InetSocketAddress; + +import static io.trino.tempto.assertions.QueryAssert.Row.row; +import static io.trino.tests.product.TestGroups.PROFILE_SPECIFIC_TESTS; +import static io.trino.tests.product.TestGroups.SCYLLA; +import static io.trino.tests.product.utils.QueryExecutors.onTrino; +import static org.assertj.core.api.Assertions.assertThat; + +public class TestScylla + extends ProductTest +{ + @Inject + private Configuration configuration; + + @BeforeMethodWithContext + public void setUp() + { + onScylla("DROP KEYSPACE IF EXISTS test"); + onScylla("CREATE KEYSPACE test WITH replication={'class':'SimpleStrategy', 'replication_factor':1}"); + } + + @Test(groups = {SCYLLA, PROFILE_SPECIFIC_TESTS}) + public void testCreateTableAsSelect() + { + onTrino().executeQuery("DROP TABLE IF EXISTS scylla.test.nation"); + QueryResult result = onTrino().executeQuery("CREATE TABLE scylla.test.nation AS SELECT * FROM tpch.tiny.nation"); + try { + assertThat(result).updatedRowsCountIsEqualTo(25); + assertThat(onTrino().executeQuery("SELECT COUNT(*) FROM scylla.test.nation")) + .containsOnly(row(25)); + } + finally { + onTrino().executeQuery("DROP TABLE scylla.test.nation"); + } + } + + private void onScylla(@Language("SQL") String query) + { + try (CqlSession session = CqlSession.builder() + .addContactPoint(new InetSocketAddress(configuration.getStringMandatory("databases.scylla.host"), configuration.getIntMandatory("databases.scylla.port"))) + .withLocalDatacenter(configuration.getStringMandatory("databases.scylla.local_datacenter")) + .build()) { + session.execute(query); + } + } +} diff --git a/testing/trino-product-tests/src/main/resources/tempto-configuration.yaml b/testing/trino-product-tests/src/main/resources/tempto-configuration.yaml index 839c23c7b112..fdea1ffa5a17 100644 --- a/testing/trino-product-tests/src/main/resources/tempto-configuration.yaml +++ b/testing/trino-product-tests/src/main/resources/tempto-configuration.yaml @@ -136,6 +136,11 @@ databases: request: timeout_seconds: 30 + scylla: + host: scylla + port: 9042 + local_datacenter: datacenter1 + sqlserver: jdbc_driver_class: com.microsoft.sqlserver.jdbc.SQLServerDriver jdbc_url: jdbc:sqlserver://sqlserver;encrypt=false diff --git a/testing/trino-server-dev/etc/catalog/scylla.properties b/testing/trino-server-dev/etc/catalog/scylla.properties new file mode 100644 index 000000000000..e264b15f0548 --- /dev/null +++ b/testing/trino-server-dev/etc/catalog/scylla.properties @@ -0,0 +1,5 @@ +connector.name=scylla +cassandra.contact-points=scylla +cassandra.load-policy.use-dc-aware=true +cassandra.load-policy.dc-aware.local-dc=datacenter1 +cassandra.allow-drop-table=true diff --git a/testing/trino-server-dev/etc/config.properties b/testing/trino-server-dev/etc/config.properties index b786657e8d2b..815d068bc6f9 100644 --- a/testing/trino-server-dev/etc/config.properties +++ b/testing/trino-server-dev/etc/config.properties @@ -34,6 +34,7 @@ plugin.bundles=\ ../../plugin/trino-delta-lake/pom.xml,\ ../../plugin/trino-blackhole/pom.xml,\ ../../plugin/trino-cassandra/pom.xml,\ + ../../plugin/trino-scylla/pom.xml,\ ../../plugin/trino-memory/pom.xml,\ ../../plugin/trino-jmx/pom.xml,\ ../../plugin/trino-raptor-legacy/pom.xml,\