From 28405e87107c30ebae4f07eeb0e2b4be9aaf2044 Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Tue, 2 Dec 2025 23:21:29 -0800 Subject: [PATCH 1/8] Modified multiple files to address PR comments and added a test file to include a test for verifying class loading --- .../integration/DatabaseConfigFactory.java | 2 +- .../integration/TeradataQueryRunner.java | 7 +++- .../integration/TeradataTestConstants.java | 8 ++-- .../integration/TestTeradataClassLoading.java | 16 +++++++ .../TestTeradataConnectorTest.java | 30 ++++++------- .../integration/TestTeradataTypeMapping.java | 34 +++++++-------- .../clearscape/ClearScapeManager.java | 38 ++++++++--------- .../clearscape/ClearScapeSetup.java | 4 +- .../clearscape/TeradataHttpClient.java | 42 ++++++++----------- 9 files changed, 96 insertions(+), 85 deletions(-) create mode 100644 plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/DatabaseConfigFactory.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/DatabaseConfigFactory.java index 24be04ec2d81..794392f1e5db 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/DatabaseConfigFactory.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/DatabaseConfigFactory.java @@ -30,7 +30,7 @@ public static DatabaseConfig create(String envName) String hostName = null; if (isEnvSet("CLEARSCAPE_TOKEN")) { - userName = TeradataTestConstants.ENV_CLEARSCAPE_USERNAME; + userName = TeradataTestConstants.CLEARSCAPE_USERNAME; password = requireEnv("CLEARSCAPE_PASSWORD"); } else { diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataQueryRunner.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataQueryRunner.java index 661538739395..3de5784e099e 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataQueryRunner.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataQueryRunner.java @@ -107,14 +107,17 @@ public DistributedQueryRunner build() return super.build(); } - public static void main(String[] args) + static void main() throws Exception { Logging logger = Logging.initialize(); logger.setLevel("io.trino.plugin.teradata", Level.DEBUG); logger.setLevel("io.trino", Level.INFO); TestingTeradataServer server = new TestingTeradataServer("TeradataQueryRunner", false); - QueryRunner queryRunner = builder(server).addCoordinatorProperty("http-server.http.port", "8080").setInitialTables(TpchTable.getTables()).build(); + QueryRunner queryRunner = builder(server) + .addCoordinatorProperty("http-server.http.port", "8080") + .setInitialTables(TpchTable.getTables()) + .build(); Logger log = Logger.get(TeradataQueryRunner.class); log.info("======== SERVER STARTED ========"); diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java index 45d0232bb3e0..a3286e992585 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java @@ -13,8 +13,10 @@ */ package io.trino.plugin.teradata.integration; -public interface TeradataTestConstants +public final class TeradataTestConstants { - String ENV_CLEARSCAPE_URL = "https://api.clearscape.teradata.com"; - String ENV_CLEARSCAPE_USERNAME = "demo_user"; + public static String CLEARSCAPE_URL = "https://api.clearscape.teradata.com"; + public static String CLEARSCAPE_USERNAME = "demo_user"; + + private TeradataTestConstants() {} } diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java new file mode 100644 index 000000000000..6d92a96c98b4 --- /dev/null +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java @@ -0,0 +1,16 @@ +package io.trino.plugin.teradata.integration; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TestTeradataClassLoading +{ + @Test + void testPluginClassLoadable() throws Exception + { + Class pluginClass = Class.forName("io.trino.plugin.teradata.TeradataPlugin"); + Object pluginInstance = pluginClass.getDeclaredConstructor().newInstance(); + assertThat(pluginInstance).isNotNull(); + } +} diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataConnectorTest.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataConnectorTest.java index 41861ccc07aa..3fa60fcb6d6f 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataConnectorTest.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataConnectorTest.java @@ -49,21 +49,6 @@ final class TestTeradataConnectorTest private TestingTeradataServer database; - private static void verifyResultOrFailure(AssertProvider queryAssertProvider, Consumer verifyResults, - Consumer verifyFailure) - { - requireNonNull(verifyResults, "verifyResults is null"); - requireNonNull(verifyFailure, "verifyFailure is null"); - QueryAssertions.QueryAssert queryAssert = assertThat(queryAssertProvider); - verifyResults.accept(queryAssert); - } - - @Override - protected SqlExecutor onRemoteDatabase() - { - return database; - } - @Override protected QueryRunner createQueryRunner() throws Exception @@ -551,4 +536,19 @@ public void testCaseSensitiveDataMapping() { super.testCaseSensitiveDataMapping(); } + + private static void verifyResultOrFailure(AssertProvider queryAssertProvider, Consumer verifyResults, + Consumer verifyFailure) + { + requireNonNull(verifyResults, "verifyResults is null"); + requireNonNull(verifyFailure, "verifyFailure is null"); + QueryAssertions.QueryAssert queryAssert = assertThat(queryAssertProvider); + verifyResults.accept(queryAssert); + } + + @Override + protected SqlExecutor onRemoteDatabase() + { + return database; + } } diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataTypeMapping.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataTypeMapping.java index 157f21ef8d62..b96d540ecef7 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataTypeMapping.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataTypeMapping.java @@ -64,7 +64,7 @@ void testByteint() .addRoundTrip("byteint", "127", TINYINT, "CAST(127 AS TINYINT)") .addRoundTrip("byteint", "-128", TINYINT, "CAST(-128 AS TINYINT)") .addRoundTrip("byteint", "null", TINYINT, "CAST(null AS TINYINT)") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("byteint")); + .execute(getQueryRunner(), teradataCreateAndInsert("byteint")); } @Test @@ -75,7 +75,7 @@ void testSmallint() .addRoundTrip("smallint", "32767", SMALLINT, "CAST(32767 AS SMALLINT)") .addRoundTrip("smallint", "-32768", SMALLINT, "CAST(-32768 AS SMALLINT)") .addRoundTrip("smallint", "null", SMALLINT, "CAST(null AS SMALLINT)") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("smallint")); + .execute(getQueryRunner(), teradataCreateAndInsert("smallint")); } @Test @@ -86,7 +86,7 @@ void testInteger() .addRoundTrip("integer", "2147483647", INTEGER, "2147483647") .addRoundTrip("integer", "-2147483648", INTEGER, "-2147483648") .addRoundTrip("integer", "NULL", INTEGER, "CAST(NULL AS INTEGER)") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("integer")); + .execute(getQueryRunner(), teradataCreateAndInsert("integer")); } @Test @@ -97,7 +97,7 @@ void testBigint() .addRoundTrip("bigint", "9223372036854775807", BIGINT, "9223372036854775807") .addRoundTrip("bigint", "-9223372036854775808", BIGINT, "-9223372036854775808") .addRoundTrip("bigint", "NULL", BIGINT, "CAST(NULL AS BIGINT)") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("bigint")); + .execute(getQueryRunner(), teradataCreateAndInsert("bigint")); } @Test @@ -116,7 +116,7 @@ void testFloat() .addRoundTrip("float", "NULL", DOUBLE, "CAST(NULL AS DOUBLE)") .addRoundTrip("real", "NULL", DOUBLE, "CAST(NULL AS DOUBLE)") .addRoundTrip("double precision", "NULL", DOUBLE, "CAST(NULL AS DOUBLE)") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("float")); + .execute(getQueryRunner(), teradataCreateAndInsert("float")); } @Test @@ -150,7 +150,7 @@ void testDecimal() .addRoundTrip("decimal(38, 0)", "-12345678901234567890123456789012345678", createDecimalType(38, 0), "CAST('-12345678901234567890123456789012345678' AS decimal(38, 0))") .addRoundTrip("numeric(38, 0)", "-12345678901234567890123456789012345678", createDecimalType(38, 0), "CAST('-12345678901234567890123456789012345678' AS decimal(38, 0))") .addRoundTrip("decimal(1, 0)", "null", createDecimalType(1, 0), "CAST(null AS decimal(1, 0))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("decimal")); + .execute(getQueryRunner(), teradataCreateAndInsert("decimal")); } @Test @@ -163,7 +163,7 @@ void testNumber() .addRoundTrip("number(38,2)", "123456789012345678901234567890123456.78", createDecimalType(38, 2), "CAST('123456789012345678901234567890123456.78' AS decimal(38, 2))") .addRoundTrip("numeric(38)", "12345678901234567890123456789012345678", createDecimalType(38, 0), "CAST('12345678901234567890123456789012345678' AS decimal(38, 0))") .addRoundTrip("numeric(3)", "null", createDecimalType(3, 0), "CAST(null AS decimal(3, 0))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("number")); + .execute(getQueryRunner(), teradataCreateAndInsert("number")); } @Test @@ -183,20 +183,20 @@ void testChar() .addRoundTrip("char(3)", "'A C'", createCharType(3), "CAST('A C' AS char(3))") .addRoundTrip("char(3)", "' BC'", createCharType(3), "CAST(' BC' AS char(3))") .addRoundTrip("char(3)", "null", createCharType(3), "CAST(null AS char(3))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("char")); + .execute(getQueryRunner(), teradataCreateAndInsert("char")); String tmode = database.getTMode(); if (tmode.equals("TERA")) { // truncation create() .addRoundTrip("char(3)", "'ABCD'", createCharType(3), "CAST('ABCD' AS char(3))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("chart")); + .execute(getQueryRunner(), teradataCreateAndInsert("chart")); } else { // Error on truncation assertThatThrownBy(() -> create() .addRoundTrip("char(3)", "'ABCD'", createCharType(3), "CAST('ABCD' AS char(3))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("chart"))) + .execute(getQueryRunner(), teradataCreateAndInsert("chart"))) .isInstanceOf(RuntimeException.class) .hasCauseInstanceOf(SQLException.class) .cause() @@ -205,7 +205,7 @@ void testChar() // max-size create() .addRoundTrip("char(64000)", "'max'", createCharType(64000), "CAST('max' AS char(64000))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("charl")); + .execute(getQueryRunner(), teradataCreateAndInsert("charl")); } @Test @@ -226,20 +226,20 @@ void testVarchar() .addRoundTrip("varchar(32)", "'A C'", createVarcharType(32), "CAST('A C' AS varchar(32))") .addRoundTrip("varchar(32)", "' BC'", createVarcharType(32), "CAST(' BC' AS varchar(32))") .addRoundTrip("varchar(32)", "null", createVarcharType(32), "CAST(null AS varchar(32))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("varchar")); + .execute(getQueryRunner(), teradataCreateAndInsert("varchar")); String teraMode = database.getTMode(); if (teraMode.equals("TERA")) { // truncation create() .addRoundTrip("varchar(3)", "'ABCD'", createVarcharType(3), "CAST('ABCD' AS varchar(3))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("varchart")); + .execute(getQueryRunner(), teradataCreateAndInsert("varchart")); } else { // Error on truncation assertThatThrownBy(() -> create() .addRoundTrip("varchar(3)", "'ABCD'", createVarcharType(3), "CAST('ABCD' AS varchar(3))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("varchart"))) + .execute(getQueryRunner(), teradataCreateAndInsert("varchart"))) .isInstanceOf(RuntimeException.class) .hasCauseInstanceOf(SQLException.class) .cause() @@ -248,7 +248,7 @@ void testVarchar() // max-size create() .addRoundTrip("long varchar", "'max'", createVarcharType(64000), "CAST('max' AS varchar(64000))") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("varcharl")); + .execute(getQueryRunner(), teradataCreateAndInsert("varcharl")); } @Test @@ -271,10 +271,10 @@ void testDate() .addRoundTrip("date", "DATE '2024-02-29'", DATE, "DATE '2024-02-29'") .addRoundTrip("date", "DATE '9999-12-30'", DATE, "DATE '9999-12-30'") .addRoundTrip("date", "NULL", DATE, "CAST(NULL AS DATE)") - .execute(getQueryRunner(), teradataJDBCCreateAndInsert("date")); + .execute(getQueryRunner(), teradataCreateAndInsert("date")); } - private DataSetup teradataJDBCCreateAndInsert(String tableNamePrefix) + private DataSetup teradataCreateAndInsert(String tableNamePrefix) { String prefix = format("%s.%s", database.getDatabaseName(), tableNamePrefix); return new CreateAndInsertDataSetup(database, prefix); diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java index 99cf05c6cfbe..d25470d3cad6 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java @@ -26,24 +26,22 @@ public class ClearScapeManager Pattern.compile("^(https?://)(www\\.)?api.clearscape.teradata\\.com.*"); private Model model; - private boolean isValidUrl(String url) - { - return ALLOWED_URL_PATTERN.matcher(url).matches(); - } - private TeradataHttpClient getTeradataHttpClient() throws URISyntaxException { - String envUrl = TeradataTestConstants.ENV_CLEARSCAPE_URL; + String envUrl = TeradataTestConstants.CLEARSCAPE_URL; if (isValidUrl(envUrl)) { return new TeradataHttpClient(envUrl); } - else { - throw new URISyntaxException(envUrl, "Provide valid environment URL"); - } + throw new URISyntaxException(envUrl, "Provide valid environment URL"); + } + + private static boolean isValidUrl(String url) + { + return ALLOWED_URL_PATTERN.matcher(url).matches(); } - public void init(Model model) + public ClearScapeManager(Model model) { this.model = model; } @@ -73,8 +71,8 @@ private EnvironmentResponse.State getClearScapeInstanceStatus() try { TeradataHttpClient teradataHttpClient = getTeradataHttpClient(); - String token = this.model.getToken(); - String name = this.model.getEnvName(); + String token = model.getToken(); + String name = model.getEnvName(); EnvironmentResponse response = null; try { response = teradataHttpClient.getEnvironment(new GetEnvironmentRequest(name), token); @@ -100,8 +98,8 @@ private void createAndStartClearScapeInstance() try { TeradataHttpClient teradataHttpClient = getTeradataHttpClient(); - String token = this.model.getToken(); - String name = this.model.getEnvName(); + String token = model.getToken(); + String name = model.getEnvName(); EnvironmentResponse response = null; try { response = teradataHttpClient.getEnvironment(new GetEnvironmentRequest(name), token); @@ -115,7 +113,7 @@ private void createAndStartClearScapeInstance() name, model.getRegion(), model.getPassword()); - response = teradataHttpClient.createEnvironment(request, token).get(); + response = teradataHttpClient.createEnvironment(request, token); } else if (response.state() == EnvironmentResponse.State.STOPPED) { EnvironmentRequest request = new EnvironmentRequest(name, new OperationRequest("start")); @@ -134,8 +132,8 @@ private void stopClearScapeInstance() { try { TeradataHttpClient teradataHttpClient = getTeradataHttpClient(); - String token = this.model.getToken(); - String name = this.model.getEnvName(); + String token = model.getToken(); + String name = model.getEnvName(); EnvironmentResponse response = null; try { @@ -160,13 +158,13 @@ private void shutdownAndDestroyClearScapeInstance() { try { TeradataHttpClient teradataHttpClient = getTeradataHttpClient(); - String token = this.model.getToken(); - DeleteEnvironmentRequest request = new DeleteEnvironmentRequest(this.model.getEnvName()); + String token = model.getToken(); + DeleteEnvironmentRequest request = new DeleteEnvironmentRequest(model.getEnvName()); teradataHttpClient.deleteEnvironment(request, token).get(); } catch (BaseException be) { log.info("Environment %s is not available. Error - %s", - this.model.getEnvName(), be.getMessage()); + model.getEnvName(), be.getMessage()); } catch (Exception e) { throw new RuntimeException("Failed to shutdown and destroy ClearScape instance", e); diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeSetup.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeSetup.java index 0af3a09727bf..2f9286592a3a 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeSetup.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeSetup.java @@ -62,9 +62,9 @@ private Model createModel() { Model model = new Model(); model.setEnvName(envName); - model.setUserName(TeradataTestConstants.ENV_CLEARSCAPE_USERNAME); + model.setUserName(TeradataTestConstants.CLEARSCAPE_USERNAME); model.setPassword(password); - model.setDatabaseName(TeradataTestConstants.ENV_CLEARSCAPE_USERNAME); + model.setDatabaseName(TeradataTestConstants.CLEARSCAPE_USERNAME); model.setToken(token); model.setRegion(region); return model; diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java index d356104d8749..170ad9cd255a 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java @@ -25,6 +25,7 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import static com.google.common.net.HttpHeaders.AUTHORIZATION; @@ -41,15 +42,8 @@ public class TeradataHttpClient public TeradataHttpClient(String baseUrl) { - this(HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build(), baseUrl); - } - - public TeradataHttpClient( - HttpClient httpClient, - String baseUrl) - { - this.httpClient = httpClient; - this.baseUrl = baseUrl; + this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build(); + this.baseUrl = Objects.requireNonNull(baseUrl, "baseUrl is null"); this.objectMapper = JsonMapper.builder() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, false) @@ -57,36 +51,36 @@ public TeradataHttpClient( } // Creating an environment is a blocking operation by default, and it takes ~1.5min to finish - public CompletableFuture createEnvironment(CreateEnvironmentRequest createEnvironmentRequest, - String token) + public EnvironmentResponse createEnvironment(CreateEnvironmentRequest createEnvironmentRequest, String token) { - var requestBody = handleCheckedException(() -> objectMapper.writeValueAsString(createEnvironmentRequest)); - var httpRequest = HttpRequest.newBuilder(URI.create(baseUrl.concat("/environments"))) + String requestBody = handleCheckedException(() -> objectMapper.writeValueAsString(createEnvironmentRequest)); + HttpRequest httpRequest = HttpRequest.newBuilder(URI.create(baseUrl.concat("/environments"))) .headers( AUTHORIZATION, BEARER + token, CONTENT_TYPE, APPLICATION_JSON) .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); - return httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString()) - .thenApply(httpResponse -> handleHttpResponse(httpResponse, new TypeReference<>() {})); + + HttpResponse httpResponse = handleCheckedException(() -> httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString())); + return handleHttpResponse(httpResponse, new TypeReference() {}); } public EnvironmentResponse getEnvironment(GetEnvironmentRequest getEnvironmentRequest, String token) { - var httpRequest = HttpRequest.newBuilder(URI.create(baseUrl + HttpRequest httpRequest = HttpRequest.newBuilder(URI.create(baseUrl .concat("/environments/") .concat(getEnvironmentRequest.name()))) .headers(AUTHORIZATION, BEARER + token) .GET() .build(); - var httpResponse = + HttpResponse httpResponse = handleCheckedException(() -> httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString())); return handleHttpResponse(httpResponse, new TypeReference<>() {}); } public CompletableFuture deleteEnvironment(DeleteEnvironmentRequest deleteEnvironmentRequest, String token) { - var httpRequest = HttpRequest.newBuilder(URI.create(baseUrl + "/environments/" + deleteEnvironmentRequest.name())) + HttpRequest httpRequest = HttpRequest.newBuilder(URI.create(baseUrl + "/environments/" + deleteEnvironmentRequest.name())) .headers(AUTHORIZATION, BEARER + token) .DELETE() .build(); @@ -98,20 +92,20 @@ public CompletableFuture deleteEnvironment(DeleteEnvironmentRequest delete public void startEnvironment(EnvironmentRequest environmentRequest, String token) { - var requestBody = handleCheckedException(() -> objectMapper.writeValueAsString(environmentRequest.request())); + String requestBody = handleCheckedException(() -> objectMapper.writeValueAsString(environmentRequest.request())); getVoidCompletableFuture(environmentRequest.name(), token, requestBody); } public void stopEnvironment(EnvironmentRequest environmentRequest, String token) { - var requestBody = handleCheckedException(() -> objectMapper.writeValueAsString(environmentRequest.request())); + String requestBody = handleCheckedException(() -> objectMapper.writeValueAsString(environmentRequest.request())); getVoidCompletableFuture(environmentRequest.name(), token, requestBody); } private void getVoidCompletableFuture(String name, String token, String jsonPayLoadString) { HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.ofString(jsonPayLoadString); - var httpRequest = HttpRequest.newBuilder(URI.create(baseUrl + "/environments/" + name)) + HttpRequest httpRequest = HttpRequest.newBuilder(URI.create(baseUrl + "/environments/" + name)) .headers(AUTHORIZATION, BEARER + token, CONTENT_TYPE, APPLICATION_JSON) .method("PATCH", publisher) .build(); @@ -121,7 +115,7 @@ private void getVoidCompletableFuture(String name, String token, String jsonPayL private T handleHttpResponse(HttpResponse httpResponse, TypeReference typeReference) { - var body = httpResponse.body(); + String body = httpResponse.body(); if (httpResponse.statusCode() >= 200 && httpResponse.statusCode() <= 299) { return handleCheckedException(() -> { if (typeReference.getType().getTypeName().equals(Void.class.getTypeName())) { @@ -138,9 +132,7 @@ else if (httpResponse.statusCode() >= 400 && httpResponse.statusCode() <= 499) { else if (httpResponse.statusCode() >= 500 && httpResponse.statusCode() <= 599) { throw new Error5xxException(httpResponse.statusCode(), body); } - else { - throw new BaseException(httpResponse.statusCode(), body); - } + throw new BaseException(httpResponse.statusCode(), body); } private static T handleCheckedException(CheckedSupplier checkedSupplier) From 6eae58df49206a4aea25ca847a351daa764d6e41 Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Tue, 2 Dec 2025 23:46:59 -0800 Subject: [PATCH 2/8] Modified multiple files to address PR comments and added a test file to include a test for verifying class loading --- docs/src/main/sphinx/connector/teradata.md | 55 +++++-------------- .../clearscape/ClearScapeManager.java | 4 +- 2 files changed, 17 insertions(+), 42 deletions(-) diff --git a/docs/src/main/sphinx/connector/teradata.md b/docs/src/main/sphinx/connector/teradata.md index d0c73f4a2688..df9d51639add 100644 --- a/docs/src/main/sphinx/connector/teradata.md +++ b/docs/src/main/sphinx/connector/teradata.md @@ -12,16 +12,19 @@ data between different systems like Teradata and Hive, or between different Tera To connect to Teradata, you need: -- Teradata Database +- Teradata database. - Network access from the Trino coordinator and workers to Teradata. Port - 1025 is the default port + 1025 is the default port. ## Configuration -To configure the Teradata connector, create a catalog properties file in -`etc/catalog` named, for example, `example.properties`, to mount the Teradata -connector as the `teradata` catalog. Create the file with the following -contents, replacing the connection properties as appropriate for your setup: +The connector can query a database on a Teradata server. Create a catalog +properties file that specifies the Teradata connector by setting the +`connector.name` to `teradata`. + +For example, to access a database as the `example` catalog, create the file +`etc/catalog/example.properties`. Replace the connection properties as +appropriate for your setup: ```properties connector.name=teradata @@ -65,11 +68,11 @@ Teradata [JDBC documentation](https://teradata-docs.s3.amazonaws.com/doc/connect ### Multiple Teradata databases -You can have as many catalogs as you need, so if you have additional Teradata -databases, simply add another properties file to etc/catalog with a different -name, making sure it ends in .properties. -For example, if you name the property file sales.properties, Trino creates a -catalog named sales using the configured connector. +You can configure as many catalogs as you need, so if you have additional Teradata +databases, simply add another properties file to `etc/catalog` with a different +name. +For example, if you name the catalog file `sales.properties`, Trino creates a +catalog named `sales` using the configured connector. ## Type mapping @@ -176,36 +179,6 @@ No other types are supported. ```{include} jdbc-type-mapping.fragment ``` -## Querying Teradata - -The Teradata connector provides a schema for every Teradata database. You can -see the available Teradata databases by running SHOW SCHEMAS: - -```sql -SHOW SCHEMAS FROM teradata; -``` - -If you have a Teradata database named sales, you can view the tables in this -database by running SHOW TABLES: - -```sql -SHOW TABLES FROM teradata.sales; -``` - -You can see a list of the columns in the orders table in the sales database -using either of the following: - -```sql -DESCRIBE teradata.sales.orders; -SHOW COLUMNS FROM teradata.sales.orders; -``` - -Finally, you can access the orders table in the sales database: - -```sql -SELECT * FROM teradata.sales.orders; -``` - ## SQL support The connector provides read access to data and metadata in diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java index d25470d3cad6..5eddb039556c 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java @@ -41,7 +41,9 @@ private static boolean isValidUrl(String url) return ALLOWED_URL_PATTERN.matcher(url).matches(); } - public ClearScapeManager(Model model) + public ClearScapeManager() {} + + public void init(Model model) { this.model = model; } From 9e3d203fa049b1241332b894b7aa7ac6b101bb52 Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Wed, 3 Dec 2025 01:13:16 -0800 Subject: [PATCH 3/8] Added license header for the newly created test class --- .../integration/TestTeradataClassLoading.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java index 6d92a96c98b4..2884eb352efe 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java @@ -1,3 +1,16 @@ +/* + * 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.teradata.integration; import org.junit.jupiter.api.Test; From aebd15aca2df7958faeff4d1ee158df47771e8ec Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Wed, 3 Dec 2025 01:21:10 -0800 Subject: [PATCH 4/8] modified few import statements and other changes to avoid checkstyle violations --- .../plugin/teradata/integration/TestTeradataClassLoading.java | 3 ++- .../teradata/integration/clearscape/TeradataHttpClient.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java index 2884eb352efe..8c9d0c2facde 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TestTeradataClassLoading.java @@ -20,7 +20,8 @@ class TestTeradataClassLoading { @Test - void testPluginClassLoadable() throws Exception + void testPluginClassLoadable() + throws Exception { Class pluginClass = Class.forName("io.trino.plugin.teradata.TeradataPlugin"); Object pluginInstance = pluginClass.getDeclaredConstructor().newInstance(); diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java index 170ad9cd255a..60ee4ab3a810 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/TeradataHttpClient.java @@ -25,11 +25,11 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.util.Objects; import java.util.concurrent.CompletableFuture; import static com.google.common.net.HttpHeaders.AUTHORIZATION; import static com.google.common.net.HttpHeaders.CONTENT_TYPE; +import static java.util.Objects.requireNonNull; public class TeradataHttpClient { @@ -43,7 +43,7 @@ public class TeradataHttpClient public TeradataHttpClient(String baseUrl) { this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build(); - this.baseUrl = Objects.requireNonNull(baseUrl, "baseUrl is null"); + this.baseUrl = requireNonNull(baseUrl, "baseUrl is null"); this.objectMapper = JsonMapper.builder() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, false) From 9718dcfafddfb0938895767cc34ef43dd03397f3 Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Wed, 3 Dec 2025 01:50:55 -0800 Subject: [PATCH 5/8] Updated EnvMultinodeAllConnectors --- .../launcher/env/environment/EnvMultinodeAllConnectors.java | 1 + 1 file changed, 1 insertion(+) 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 ee3de89bd9f0..8fae4cc78e43 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 @@ -75,6 +75,7 @@ public void extendEnvironment(Environment.Builder builder) "singlestore", "snowflake", "sqlserver", + "teradata", "tpcds", "trino_thrift", "vertica") From 7fecfd5bc166c72f34eaeb8b120775c1dc5d43c6 Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Wed, 3 Dec 2025 20:52:37 -0800 Subject: [PATCH 6/8] Made TeradataTestConstants final to avoid mismatch with the expected pattern --- .../plugin/teradata/integration/TeradataTestConstants.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java index a3286e992585..df34c711ca95 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/TeradataTestConstants.java @@ -15,8 +15,8 @@ public final class TeradataTestConstants { - public static String CLEARSCAPE_URL = "https://api.clearscape.teradata.com"; - public static String CLEARSCAPE_USERNAME = "demo_user"; + public static final String CLEARSCAPE_URL = "https://api.clearscape.teradata.com"; + public static final String CLEARSCAPE_USERNAME = "demo_user"; private TeradataTestConstants() {} } From 2e17f415f8c571d876d909939998076e32f5501d Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Wed, 3 Dec 2025 22:36:42 -0800 Subject: [PATCH 7/8] removed unused constructor --- .../teradata/integration/clearscape/ClearScapeManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java index 5eddb039556c..c77bbafd70e9 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java @@ -41,7 +41,7 @@ private static boolean isValidUrl(String url) return ALLOWED_URL_PATTERN.matcher(url).matches(); } - public ClearScapeManager() {} +// public ClearScapeManager() {} public void init(Model model) { From 6c7242992cb41b4779f49f0c975557d548bba301 Mon Sep 17 00:00:00 2001 From: Dabbiru Vasudha Date: Wed, 3 Dec 2025 22:37:18 -0800 Subject: [PATCH 8/8] removed unused constructor --- .../teradata/integration/clearscape/ClearScapeManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java index c77bbafd70e9..05d1e1a5930d 100644 --- a/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java +++ b/plugin/trino-teradata/src/test/java/io/trino/plugin/teradata/integration/clearscape/ClearScapeManager.java @@ -41,8 +41,6 @@ private static boolean isValidUrl(String url) return ALLOWED_URL_PATTERN.matcher(url).matches(); } -// public ClearScapeManager() {} - public void init(Model model) { this.model = model;