Skip to content

Commit d0ba6de

Browse files
authored
New option for alternate query log tables (#343)
I'm splitting the `--query-log-alternates` option of the `teradata-logs` connector into two separate options to simplify the documentation. Before: ``` --query-log-alternates HistoricLogTable,HistoricSqlTable ``` After: ``` -Dteradata-logs.query-logs-table=HistoricLogTable -Dteradata-logs.sql-logs-table=HistoricSqlTable ``` This change will also align the naming of the new options with the existing options for other tables: ``` -Dteradata-logs.utility-logs-table -Dteradata-logs.res-usage-scpu-table -Dteradata-logs.res-usage-spma-table ``` The old option is kept for backwards compatibility.
1 parent 3df5185 commit d0ba6de

File tree

13 files changed

+552
-79
lines changed

13 files changed

+552
-79
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,20 @@ public class ConnectorArguments extends DefaultArguments {
312312
parser
313313
.acceptsAll(Arrays.asList("dry-run", "n"), "Show export actions without executing.")
314314
.forHelp();
315+
316+
public static final String OPT_QUERY_LOG_ALTERNATES_DEPRECATION_MESSAGE =
317+
"The "
318+
+ OPT_QUERY_LOG_ALTERNATES
319+
+ " option is "
320+
+ "deprecated, please use -Dteradata-logs.query-log-table and -Dteradata-logs.sql-log-table instead";
315321
private final OptionSpec<String> optionQueryLogAlternates =
316322
parser
317323
.accepts(
318324
OPT_QUERY_LOG_ALTERNATES,
319325
"pair of alternate query log tables to export (teradata-logs only), by default "
320326
+ "logTable=dbc.DBQLogTbl and queryTable=dbc.DBQLSQLTbl, if --assessment flag"
321-
+ " is enabled, then logTable=dbc.QryLogV and queryTable=dbc.DBQLSQLTbl.")
327+
+ " is enabled, then logTable=dbc.QryLogV and queryTable=dbc.DBQLSQLTbl. "
328+
+ OPT_QUERY_LOG_ALTERNATES_DEPRECATION_MESSAGE)
322329
.withRequiredArg()
323330
.ofType(String.class)
324331
.withValuesSeparatedBy(',')
@@ -851,6 +858,11 @@ public String getDefinition(@Nonnull ConnectorProperty property) {
851858
return getDefinitionMap().get(property.getName());
852859
}
853860

861+
/** Checks if the property was specified on the command-line. */
862+
public boolean isDefinitionSpecified(@Nonnull ConnectorProperty property) {
863+
return StringUtils.isNotEmpty(getDefinitionMap().get(property.getName()));
864+
}
865+
854866
private Map<String, String> getDefinitionMap() {
855867
if (definitionMap == null) {
856868
definitionMap =

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public abstract class AbstractTeradataConnector extends AbstractJdbcConnector {
9191
protected static final DateTimeFormatter SQL_FORMAT =
9292
DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneOffset.UTC);
9393
@VisibleForTesting /* pp */ static final String DEF_LOG_TABLE = "dbc.DBQLogTbl";
94-
@VisibleForTesting /* pp */ static final String DEF_QUERY_TABLE = "dbc.DBQLSQLTbl";
94+
@VisibleForTesting /* pp */ static final String DEF_SQL_TABLE = "dbc.DBQLSQLTbl";
9595

9696
protected enum CommonTeradataConnectorProperty implements ConnectorProperty {
9797
TMODE(
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2022-2023 Google LLC
3+
* Copyright 2013-2021 CompilerWorks
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.google.edwmigration.dumper.application.dumper.connector.teradata;
18+
19+
import com.google.auto.value.AutoValue;
20+
import com.google.common.base.Preconditions;
21+
22+
/**
23+
* Table names to extract the query logs from. See the description in {@link
24+
* QueryLogTableNamesResolver}.
25+
*/
26+
@AutoValue
27+
abstract class QueryLogTableNames {
28+
29+
/** @return query logs table name */
30+
abstract String queryLogsTableName();
31+
32+
/** @return SQL logs table name */
33+
abstract String sqlLogsTableName();
34+
35+
/** @return whether at least one alternate table is being used */
36+
abstract boolean usingAtLeastOneAlternate();
37+
38+
static QueryLogTableNames create(
39+
String queryLogsTableName, String sqlLogsTableName, boolean usingAtLeastOneAlternate) {
40+
Preconditions.checkArgument(
41+
!queryLogsTableName.isEmpty(), "Query log table name cannot be empty.");
42+
Preconditions.checkArgument(!sqlLogsTableName.isEmpty(), "SQL log table name cannot be empty.");
43+
return new AutoValue_QueryLogTableNames(
44+
queryLogsTableName, sqlLogsTableName, usingAtLeastOneAlternate);
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
* Copyright 2022-2023 Google LLC
3+
* Copyright 2013-2021 CompilerWorks
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.google.edwmigration.dumper.application.dumper.connector.teradata;
18+
19+
import static com.google.edwmigration.dumper.application.dumper.ConnectorArguments.OPT_QUERY_LOG_ALTERNATES;
20+
import static com.google.edwmigration.dumper.application.dumper.ConnectorArguments.OPT_QUERY_LOG_ALTERNATES_DEPRECATION_MESSAGE;
21+
import static com.google.edwmigration.dumper.application.dumper.connector.teradata.AbstractTeradataConnector.DEF_LOG_TABLE;
22+
import static com.google.edwmigration.dumper.application.dumper.connector.teradata.TeradataLogsConnector.ASSESSMENT_DEF_LOG_TABLE;
23+
import static com.google.edwmigration.dumper.application.dumper.connector.teradata.TeradataLogsConnector.TeradataLogsConnectorProperty.QUERY_LOGS_TABLE;
24+
import static com.google.edwmigration.dumper.application.dumper.connector.teradata.TeradataLogsConnector.TeradataLogsConnectorProperty.SQL_LOGS_TABLE;
25+
import static com.google.edwmigration.dumper.application.dumper.connector.teradata.TeradataUtils.nonEmpty;
26+
27+
import com.google.common.base.Preconditions;
28+
import com.google.common.collect.ImmutableList;
29+
import com.google.edwmigration.dumper.application.dumper.ConnectorArguments;
30+
import com.google.edwmigration.dumper.application.dumper.MetadataDumperUsageException;
31+
import java.util.List;
32+
import org.slf4j.Logger;
33+
import org.slf4j.LoggerFactory;
34+
35+
/**
36+
* Resolver that retrieves the names of query log tables from the command-line options.
37+
*
38+
* <p>Teradata saves query logs in two tables: {@code DBC.DBQLogTbl} and {@code DBC.DBQLSqlTbl}.
39+
* These two tables are called query log table and SQL log table for the purposes of the query logs
40+
* extraction.
41+
*
42+
* <p>Depending on the flags provided on the command-line, the {@code teradata-logs} connector uses
43+
* different pair of source tables for extraction:
44+
*
45+
* <ul>
46+
* <li>If the {@code --assessment} flag is not used, then the logs are extracted from tables
47+
* {@code DBC.DBQLogTbl} and {@code DBC.DBQLSqlTbl}
48+
* <li>If the {@code --assessment} flag is used, then the logs are extracted from tables {@code
49+
* DBC.QryLogV} (a view that selects the logs from {@code DBC.DBQLogTbl} table) and {@code
50+
* DBC.DBQLSqlTbl}
51+
* </ul>
52+
*
53+
* <p>Additionally, the user can specify an alternative table for each of the two tables:
54+
*
55+
* <ul>
56+
* <li>For the query log table, the command-line flag is: {@code -Dteradata-logs.query-log-table}
57+
* <li>For the SQL log table, the command-line flag is: {@code -Dteradata-logs.sql-log-table}
58+
* </ul>
59+
*
60+
* <p>Deprecated: There is also a second way of specifying both alternative tables by using the
61+
* {@code --query-log-alternates} command-line flag that accepts these two log tables as a parameter
62+
* (separated by a comma).
63+
*/
64+
class QueryLogTableNamesResolver {
65+
private static final Logger LOG = LoggerFactory.getLogger(QueryLogTableNamesResolver.class);
66+
67+
private static final String TERADATA_LOGS_CONNECTOR_NAME = "teradata-logs";
68+
69+
static QueryLogTableNames resolve(ConnectorArguments arguments) {
70+
Preconditions.checkArgument(
71+
arguments.getConnectorName().equalsIgnoreCase(TERADATA_LOGS_CONNECTOR_NAME),
72+
"Resolver requires the connector to be '%s'.",
73+
TERADATA_LOGS_CONNECTOR_NAME);
74+
if (arguments.getQueryLogAlternates().isEmpty()) {
75+
return resolveFromDefinitionOptions(arguments);
76+
}
77+
return resolveFromLegacyOption(arguments);
78+
}
79+
80+
private static QueryLogTableNames resolveFromDefinitionOptions(ConnectorArguments arguments) {
81+
boolean alternateQueryLogTableSpecified = arguments.isDefinitionSpecified(QUERY_LOGS_TABLE);
82+
boolean alternateSqlLogTableSpecified = arguments.isDefinitionSpecified(SQL_LOGS_TABLE);
83+
String queryLogTable =
84+
nonEmpty(arguments.getDefinition(QUERY_LOGS_TABLE))
85+
.orElse(arguments.isAssessment() ? ASSESSMENT_DEF_LOG_TABLE : DEF_LOG_TABLE);
86+
String sqlLogTable = arguments.getDefinitionOrDefault(SQL_LOGS_TABLE);
87+
if (alternateQueryLogTableSpecified && !alternateSqlLogTableSpecified) {
88+
LOG.warn(
89+
"The alternate query log table was provided using the '-D{}' flag, but no"
90+
+ " alternate SQL table was provided using the '-D{}' flag. The following tables"
91+
+ " will be joined to extract the query logs: '{}' and '{}'.",
92+
QUERY_LOGS_TABLE.getName(),
93+
SQL_LOGS_TABLE.getName(),
94+
queryLogTable,
95+
sqlLogTable);
96+
} else if (!alternateQueryLogTableSpecified && alternateSqlLogTableSpecified) {
97+
LOG.warn(
98+
"The alternate SQL log table was provided using the '-D{}' flag, but no alternate"
99+
+ " query table was provided using the '-D{}' flag. The following tables will be"
100+
+ " joined to extract the query logs: '{}' and '{}'.",
101+
SQL_LOGS_TABLE.getName(),
102+
QUERY_LOGS_TABLE.getName(),
103+
queryLogTable,
104+
sqlLogTable);
105+
}
106+
return QueryLogTableNames.create(
107+
queryLogTable,
108+
sqlLogTable,
109+
alternateQueryLogTableSpecified || alternateSqlLogTableSpecified);
110+
}
111+
112+
private static final QueryLogTableNames resolveFromLegacyOption(ConnectorArguments arguments) {
113+
List<String> legacyAlternates = arguments.getQueryLogAlternates();
114+
boolean alternateQueryLogTableSpecified = arguments.isDefinitionSpecified(QUERY_LOGS_TABLE);
115+
boolean alternateSqlLogTableSpecified = arguments.isDefinitionSpecified(SQL_LOGS_TABLE);
116+
if (alternateQueryLogTableSpecified || alternateSqlLogTableSpecified) {
117+
ImmutableList.Builder<String> flagsUsed = ImmutableList.builder();
118+
flagsUsed.add(OPT_QUERY_LOG_ALTERNATES);
119+
if (alternateQueryLogTableSpecified) {
120+
flagsUsed.add(QUERY_LOGS_TABLE.getName());
121+
}
122+
if (alternateSqlLogTableSpecified) {
123+
flagsUsed.add(SQL_LOGS_TABLE.getName());
124+
}
125+
throw new MetadataDumperUsageException(
126+
String.format(
127+
"Mixed alternate query log table configuration detected in flags '%s'. (",
128+
flagsUsed.build())
129+
+ OPT_QUERY_LOG_ALTERNATES_DEPRECATION_MESSAGE
130+
+ ")");
131+
}
132+
if (legacyAlternates.size() != 2) {
133+
throw new MetadataDumperUsageException(
134+
"Alternate query log tables must be given as a pair separated by a comma;"
135+
+ " you specified: '"
136+
+ legacyAlternates
137+
+ "'. ("
138+
+ OPT_QUERY_LOG_ALTERNATES_DEPRECATION_MESSAGE
139+
+ ")");
140+
}
141+
return QueryLogTableNames.create(
142+
/* queryLogsTableName= */ legacyAlternates.get(0),
143+
/* sqlLogsTableName= */ legacyAlternates.get(1),
144+
/* usingAtLeastOneAlternate= */ true);
145+
}
146+
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,14 @@ public void addTasksTo(List<? super Task<?>> out, @Nonnull ConnectorArguments ar
272272
out.add(new FormatTask(FORMAT_NAME));
273273

274274
String logTable = DEF_LOG_TABLE;
275-
String queryTable = DEF_QUERY_TABLE;
275+
String sqlTable = DEF_SQL_TABLE;
276276
List<String> alternates = arguments.getQueryLogAlternates();
277277
if (!alternates.isEmpty()) {
278278
if (alternates.size() != 2)
279279
throw new MetadataDumperUsageException(
280280
"Alternate query log tables must be given as a pair; you specified: " + alternates);
281281
logTable = alternates.get(0);
282-
queryTable = alternates.get(1);
282+
sqlTable = alternates.get(1);
283283
}
284284

285285
// if the user specifies an earliest start time there will be extraneous empty dump files
@@ -306,15 +306,15 @@ public void addTasksTo(List<? super Task<?>> out, @Nonnull ConnectorArguments ar
306306
+ DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(interval.getStartUTC())
307307
+ ".csv";
308308
out.add(
309-
new LSqlQueryFactory(LSqlfile, state, logTable, queryTable, lSqlConditions, interval)
309+
new LSqlQueryFactory(LSqlfile, state, logTable, sqlTable, lSqlConditions, interval)
310310
.withHeaderClass(TeradataLogsDumpFormat.HeaderLSql.class));
311311

312312
String LOGfile =
313313
ZIP_ENTRY_PREFIX_LOG
314314
+ DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(interval.getStartUTC())
315315
+ ".csv";
316316
out.add(
317-
new LogQueryFactory(LOGfile, state, logTable, queryTable, logConditions, interval)
317+
new LogQueryFactory(LOGfile, state, logTable, sqlTable, logConditions, interval)
318318
.withHeaderClass(TeradataLogsDumpFormat.HeaderLog.class));
319319
}
320320
}

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -159,23 +159,14 @@ public class TeradataAssessmentLogsJdbcTask extends TeradataLogsJdbcTask {
159159
public TeradataAssessmentLogsJdbcTask(
160160
@Nonnull String targetPath,
161161
SharedState state,
162-
String logTable,
163-
String queryTable,
162+
QueryLogTableNames tableNames,
164163
Set<String> conditions,
165164
ZonedInterval interval,
166165
@CheckForNull String logDateColumn,
167166
OptionalLong maxSqlLength,
168167
List<String> orderBy) {
169168
super(
170-
targetPath,
171-
state,
172-
logTable,
173-
queryTable,
174-
conditions,
175-
interval,
176-
logDateColumn,
177-
maxSqlLength,
178-
orderBy);
169+
targetPath, state, tableNames, conditions, interval, logDateColumn, maxSqlLength, orderBy);
179170
}
180171

181172
@Nonnull

0 commit comments

Comments
 (0)