Skip to content

Commit 2c38fc0

Browse files
authored
Add new flag to change Teradata Transaction mode (#338)
The default transaction mode in the dumper is ANSI. The new command-line flag `-Dteradata.tmode` allows setting this mode to one of ANSI, TERA, DEFAULT or NONE for the `teradata` and `teradata-logs` connectors.
1 parent 67e86b9 commit 2c38fc0

File tree

6 files changed

+135
-4
lines changed

6 files changed

+135
-4
lines changed

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/MetadataDumperUsageException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*
2828
* @author matt
2929
*/
30-
public class MetadataDumperUsageException extends Exception {
30+
public class MetadataDumperUsageException extends RuntimeException {
3131

3232
private final List<String> msgs;
3333

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/teradata/AbstractTeradataConnector.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616
*/
1717
package com.google.edwmigration.dumper.application.dumper.connector.teradata;
1818

19+
import static com.google.edwmigration.dumper.application.dumper.connector.teradata.TeradataUtils.determineTransactionMode;
20+
1921
import com.google.common.annotations.VisibleForTesting;
22+
import com.google.common.base.Joiner;
2023
import com.google.common.base.Preconditions;
24+
import com.google.common.collect.ImmutableList;
2125
import com.google.common.io.ByteSink;
2226
import com.google.edwmigration.dumper.application.dumper.ConnectorArguments;
2327
import com.google.edwmigration.dumper.application.dumper.annotations.RespectsArgumentDriverClass;
@@ -28,6 +32,7 @@
2832
import com.google.edwmigration.dumper.application.dumper.annotations.RespectsArgumentUser;
2933
import com.google.edwmigration.dumper.application.dumper.annotations.RespectsInput;
3034
import com.google.edwmigration.dumper.application.dumper.connector.AbstractJdbcConnector;
35+
import com.google.edwmigration.dumper.application.dumper.connector.ConnectorProperty;
3136
import com.google.edwmigration.dumper.application.dumper.handle.Handle;
3237
import com.google.edwmigration.dumper.application.dumper.handle.JdbcHandle;
3338
import com.google.edwmigration.dumper.application.dumper.task.JdbcSelectTask;
@@ -41,6 +46,7 @@
4146
import java.time.ZoneOffset;
4247
import java.time.format.DateTimeFormatter;
4348
import java.util.List;
49+
import java.util.Optional;
4450
import java.util.concurrent.ConcurrentHashMap;
4551
import java.util.concurrent.ConcurrentMap;
4652
import javax.annotation.Nonnull;
@@ -87,6 +93,31 @@ public abstract class AbstractTeradataConnector extends AbstractJdbcConnector {
8793
@VisibleForTesting /* pp */ static final String DEF_LOG_TABLE = "dbc.DBQLogTbl";
8894
@VisibleForTesting /* pp */ static final String DEF_QUERY_TABLE = "dbc.DBQLSQLTbl";
8995

96+
protected enum CommonTeradataConnectorProperty implements ConnectorProperty {
97+
TMODE(
98+
"teradata.tmode",
99+
"Transaction mode - one of ANSI, TERA, DEFAULT or NONE. If NONE is used, then no"
100+
+ " transaction mode is included in the JDBC connection string. Default: ANSI.");
101+
102+
private final String name;
103+
private final String description;
104+
105+
CommonTeradataConnectorProperty(String name, String description) {
106+
this.name = name;
107+
this.description = description;
108+
}
109+
110+
@Nonnull
111+
public String getName() {
112+
return name;
113+
}
114+
115+
@Nonnull
116+
public String getDescription() {
117+
return description;
118+
}
119+
}
120+
90121
protected static class TeradataJdbcSelectTask extends JdbcSelectTask {
91122

92123
private final String sqlCount;
@@ -166,7 +197,13 @@ public Handle open(ConnectorArguments arguments) throws Exception {
166197
if (url == null) {
167198
String host = arguments.getHost();
168199
int port = arguments.getPort(OPT_PORT_DEFAULT);
169-
url = "jdbc:teradata://" + host + "/DBS_PORT=" + port + ",TMODE=ANSI,CHARSET=UTF8";
200+
ImmutableList.Builder<String> properties = ImmutableList.builder();
201+
properties.add("DBS_PORT=" + port);
202+
determineTransactionMode(
203+
Optional.ofNullable(arguments.getDefinition(CommonTeradataConnectorProperty.TMODE)))
204+
.ifPresent(transactionMode -> properties.add("TMODE=" + transactionMode));
205+
properties.add("CHARSET=UTF8");
206+
url = "jdbc:teradata://" + host + "/" + (Joiner.on(",").join(properties.build()));
170207
// ,MAX_MESSAGE_BODY=16777216
171208
}
172209

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/teradata/TeradataLogsConnector.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ public enum TeradataLogsConnectorProperty implements ConnectorProperty {
9898
+ " Example: 10000. Allowed range: "
9999
+ MAX_SQL_LENGTH_RANGE
100100
+ ".",
101-
/* defaultValue= */ null);
101+
/* defaultValue= */ null),
102+
TMODE(CommonTeradataConnectorProperty.TMODE);
102103

103104
private final String name;
104105
private final String description;
@@ -110,6 +111,12 @@ public enum TeradataLogsConnectorProperty implements ConnectorProperty {
110111
this.defaultValue = defaultValue;
111112
}
112113

114+
TeradataLogsConnectorProperty(CommonTeradataConnectorProperty connectorProperty) {
115+
this.name = connectorProperty.getName();
116+
this.description = connectorProperty.getDescription();
117+
this.defaultValue = null;
118+
}
119+
113120
@Nonnull
114121
public String getName() {
115122
return name;

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/teradata/TeradataMetadataConnector.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public enum TeradataMetadataConnectorProperties implements ConnectorProperty {
7979
+ " Text that is longer than the defined limit will be split into multiple rows."
8080
+ " Example: 10000. Allowed range: "
8181
+ MAX_TEXT_LENGTH_RANGE
82-
+ ".");
82+
+ "."),
83+
TMODE(CommonTeradataConnectorProperty.TMODE);
8384

8485
private final String name;
8586
private final String description;
@@ -89,6 +90,11 @@ public enum TeradataMetadataConnectorProperties implements ConnectorProperty {
8990
this.description = description;
9091
}
9192

93+
TeradataMetadataConnectorProperties(CommonTeradataConnectorProperty connectorProperty) {
94+
this.name = connectorProperty.getName();
95+
this.description = connectorProperty.getDescription();
96+
}
97+
9298
@Nonnull
9399
public String getName() {
94100
return name;

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/teradata/TeradataUtils.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
package com.google.edwmigration.dumper.application.dumper.connector.teradata;
1818

1919
import com.google.common.base.Preconditions;
20+
import com.google.common.collect.ImmutableSet;
21+
import com.google.edwmigration.dumper.application.dumper.MetadataDumperUsageException;
2022
import java.util.Optional;
2123
import java.util.function.Supplier;
2224

2325
public class TeradataUtils {
26+
private static final ImmutableSet<String> VALID_TRANSACTION_MODES =
27+
ImmutableSet.of("ANSI", "TERA", "DEFAULT", "NONE");
2428

2529
public static <T> Optional<T> optionalIf(boolean condition, Supplier<T> supplier) {
2630
return condition ? Optional.of(supplier.get()) : Optional.empty();
@@ -46,6 +50,33 @@ public static String formatQuery(String query) {
4650
return query.replaceAll("\\s+", " ").replaceAll("\\( ", "(").replaceAll(" \\)", ")").trim();
4751
}
4852

53+
/**
54+
* If the mode is not provided (empty optional), then returns the default mode - ANSI. Otherwise,
55+
* performs the validation of the transaction mode.
56+
*
57+
* @param commandLineTransactionMode command-line argument containing the transaction mode
58+
* @return validated transaction mode
59+
* @throws MetadataDumperUsageException if the mode is not supported
60+
*/
61+
static Optional<String> determineTransactionMode(Optional<String> commandLineTransactionMode)
62+
throws MetadataDumperUsageException {
63+
if (!commandLineTransactionMode.isPresent()) {
64+
return Optional.of("ANSI");
65+
}
66+
Optional<String> processedMode =
67+
commandLineTransactionMode.map(mode -> mode.trim().toUpperCase());
68+
processedMode.ifPresent(
69+
mode -> {
70+
if (!VALID_TRANSACTION_MODES.contains(mode)) {
71+
throw new MetadataDumperUsageException(
72+
String.format(
73+
"Unsupported transaction mode='%s', supported modes='%s'.",
74+
commandLineTransactionMode.get(), VALID_TRANSACTION_MODES));
75+
}
76+
});
77+
return processedMode.filter(mode -> !mode.equals("NONE"));
78+
}
79+
4980
static String createTimestampExpression(String tableAlias, String columnName) {
5081
return createTimestampExpression(Optional.of(tableAlias), columnName);
5182
}

dumper/app/src/test/java/com/google/edwmigration/dumper/application/dumper/connector/teradata/TeradataUtilsTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import static org.junit.Assert.assertEquals;
2020
import static org.junit.Assert.assertThrows;
2121

22+
import com.google.edwmigration.dumper.application.dumper.MetadataDumperUsageException;
23+
import java.util.Optional;
2224
import org.junit.Test;
2325
import org.junit.runner.RunWith;
2426
import org.junit.runners.JUnit4;
@@ -95,4 +97,52 @@ public void formatQuery_spacesInsideMultipleParentheses() {
9597

9698
assertEquals("SELECT (2 + N + (3 + N + (N + N)))", formattedQuery);
9799
}
100+
101+
@Test
102+
public void determineTransactionMode_tera() {
103+
Optional<String> transactionMode = TeradataUtils.determineTransactionMode(Optional.of("TERA"));
104+
105+
assertEquals(Optional.of("TERA"), transactionMode);
106+
}
107+
108+
@Test
109+
public void determineTransactionMode_ansi() {
110+
Optional<String> transactionMode = TeradataUtils.determineTransactionMode(Optional.of("ANSI"));
111+
112+
assertEquals(Optional.of("ANSI"), transactionMode);
113+
}
114+
115+
@Test
116+
public void determineTransactionMode_default() {
117+
Optional<String> transactionMode =
118+
TeradataUtils.determineTransactionMode(Optional.of("DEFAULT"));
119+
120+
assertEquals(Optional.of("DEFAULT"), transactionMode);
121+
}
122+
123+
@Test
124+
public void determineTransactionMode_unsupportedMode_throwsException() {
125+
MetadataDumperUsageException e =
126+
assertThrows(
127+
MetadataDumperUsageException.class,
128+
() -> TeradataUtils.determineTransactionMode(Optional.of("fast")));
129+
130+
assertEquals(
131+
"Unsupported transaction mode='fast', supported modes='[ANSI, TERA, DEFAULT, NONE]'.",
132+
e.getMessage());
133+
}
134+
135+
@Test
136+
public void determineTransactionMode_none() {
137+
Optional<String> transactionMode = TeradataUtils.determineTransactionMode(Optional.of("NONE"));
138+
139+
assertEquals(Optional.empty(), transactionMode);
140+
}
141+
142+
@Test
143+
public void determineTransactionMode_commandLineOptionNotSpecified() {
144+
Optional<String> transactionMode = TeradataUtils.determineTransactionMode(Optional.empty());
145+
146+
assertEquals(Optional.of("ANSI"), transactionMode);
147+
}
98148
}

0 commit comments

Comments
 (0)