Skip to content

Commit

Permalink
Merge pull request #45 from project-tsurugi/feat-tgdump-sql
Browse files Browse the repository at this point in the history
feat: tgdump can now use any SQL statement by `--sql`.
  • Loading branch information
ashigeru authored Jan 8, 2025
2 parents 054079e + 38a0373 commit 8f8f0e5
Show file tree
Hide file tree
Showing 34 changed files with 3,102 additions and 921 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@
import com.beust.jcommander.ParameterException;
import com.tsurugidb.tools.common.connection.ConnectionProvider;
import com.tsurugidb.tools.tgdump.core.engine.DumpTargetSelector;
import com.tsurugidb.tools.tgdump.core.engine.QueryDumpTargetSelector;
import com.tsurugidb.tools.tgdump.core.engine.TableDumpTargetSelector;
import com.tsurugidb.tools.tgdump.core.model.TransactionSettings;
import com.tsurugidb.tools.tgdump.core.model.TransactionSettings.Type;
import com.tsurugidb.tools.tgdump.profile.DumpProfileBundleLoader;
import com.tsurugidb.tools.tgdump.profile.DumpProfileReader;

Expand Down Expand Up @@ -123,7 +124,7 @@ public TransactionTypeConverter(String optionName) {
"read-only", DEFAULT_TRANSACTION_TYPE);

@Override
public Type convert(String value) {
public TransactionSettings.Type convert(String value) {
var result = NAMES.get(value.toLowerCase(Locale.ENGLISH));
if (result == null) {
throw new ParameterException(MessageFormat.format(
Expand All @@ -143,7 +144,7 @@ public Type convert(String value) {
/**
* The default transaction type ({@link com.tsurugidb.tools.tgdump.core.model.TransactionSettings.Type#RTX RTX}).
*/
public static final Type DEFAULT_TRANSACTION_TYPE = TransactionSettings.Type.RTX;
public static final TransactionSettings.Type DEFAULT_TRANSACTION_TYPE = TransactionSettings.Type.RTX;

/**
* The default number of dump operation worker threads.
Expand All @@ -164,6 +165,8 @@ public Type convert(String value) {
required = true)
private List<String> tableNames;

private boolean queryMode = false;

private Path destinationPath;

private Path profile = Path.of(DEFAULT_PROFILE);
Expand Down Expand Up @@ -198,10 +201,10 @@ public Type convert(String value) {

private ConnectionProvider connectionProvider;


/**
* Returns the dump target table names.
* @return the table name list
* @see #isQueryMode()
*/
public List<String> getTableNames() {
if (tableNames == null) {
Expand All @@ -220,6 +223,29 @@ public void setTableNames(@Nonnull List<String> nameList) {
this.tableNames = List.copyOf(nameList);
}

/**
* Returns whether to specify query text instead of table names.
* @return {@code true} if use query text, or {@code false} if use table names
*/
public boolean isQueryMode() {
return queryMode;
}

/**
* Sets whether to specify query text instead of table names.
* @param enable {@code true} to allow query text, {@code false} to use table names
*/
@Parameter(
order = 10,
names = { "--sql" },
arity = 0,
description = "specify SQL text instead of table names",
required = false)
public void setQueryMode(boolean enable) {
LOG.trace("argument: --sql: {}", enable); //$NON-NLS-1$
this.queryMode = enable;
}

/**
* Returns the dump files destination path.
* @return the destination path
Expand All @@ -236,7 +262,7 @@ public Path getDestinationPath() {
order = 10,
names = { "--to" },
arity = 1,
description = "Destination directory of table dump files.",
description = "Destination directory of dump files.",
required = true)
public void setDestinationPath(@Nonnull Path path) {
Objects.requireNonNull(path);
Expand Down Expand Up @@ -525,10 +551,10 @@ public void setPrintVersion(boolean enable) {
* @return the dump profile reader
*/
protected DumpProfileReader getProfileReader() {
if (profileReader == null) {
this.profileReader = new DumpProfileReader();
if (profileReader != null) {
return profileReader;
}
return profileReader;
return new DumpProfileReader();
}

/**
Expand All @@ -552,13 +578,13 @@ protected void setProfileReader(@Nullable DumpProfileReader value) {
* @return the dump profile bundle loader
*/
protected DumpProfileBundleLoader getProfileBundleLoader() {
if (profileBundleLoader == null) {
this.profileBundleLoader = new DumpProfileBundleLoader(
getProfileReader(),
CommandArgumentSet.class.getClassLoader(),
true);
if (profileBundleLoader != null) {
return profileBundleLoader;
}
return profileBundleLoader;
return new DumpProfileBundleLoader(
getProfileReader(),
CommandArgumentSet.class.getClassLoader(),
true);
}

/**
Expand All @@ -582,10 +608,13 @@ protected void setProfileBundleLoader(@Nullable DumpProfileBundleLoader value) {
* @return the dump target selector
*/
protected DumpTargetSelector getTargetSelector() {
if (targetSelector == null) {
this.targetSelector = new DumpTargetSelector();
if (targetSelector != null) {
return this.targetSelector;
}
if (queryMode) {
return new QueryDumpTargetSelector();
}
return targetSelector;
return new TableDumpTargetSelector();
}

/**
Expand All @@ -609,10 +638,10 @@ protected void setTargetSelector(@Nullable DumpTargetSelector value) {
* @return the connection provider
*/
protected ConnectionProvider getConnectionProvider() {
if (connectionProvider == null) {
this.connectionProvider = new ConnectionProvider();
if (connectionProvider != null) {
return connectionProvider;
}
return connectionProvider;
return new ConnectionProvider();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.slf4j.LoggerFactory;

import com.tsurugidb.tools.common.diagnostic.DiagnosticException;
import com.tsurugidb.tools.common.diagnostic.DiagnosticUtil;
import com.tsurugidb.tools.common.monitoring.CompositeMonitor;
import com.tsurugidb.tools.common.monitoring.JsonMonitor;
import com.tsurugidb.tools.common.monitoring.LoggingMonitor;
Expand Down Expand Up @@ -84,6 +85,7 @@ static void printArgumentSet(@Nonnull Printer printer, @Nonnull CommandArgumentS

// dump core settings
printArgument(printer, "(positional)", args.getTableNames());
printArgument(printer, "--sql", args.isQueryMode()); //$NON-NLS-1$
printArgument(printer, "--to", args.getDestinationPath()); //$NON-NLS-1$
printArgument(printer, "--profile", args.getProfile()); //$NON-NLS-1$

Expand Down Expand Up @@ -171,8 +173,15 @@ static List<DumpTarget> prepareDestination(
e);
}

LOG.debug("compute individual table dump output directories");
var targets = selector.getTargets(destination, tableNames);
LOG.debug("compute individual dump output directories");
List<DumpTarget> targets;
try {
targets = selector.getTargets(destination, tableNames);
} catch (IllegalArgumentException e) {
throw new CliException(CliDiagnosticCode.INVALID_PARAMETER,
List.of(DiagnosticUtil.getMessage(e)),
e);
}
LOG.debug("dump targets: {}", targets);
return targets;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import com.google.protobuf.Message;
import com.google.protobuf.TextFormat;
import com.tsurugidb.tools.common.monitoring.MonitoringException;
import com.tsurugidb.tools.tgdump.core.engine.DumpMonitor;
import com.tsurugidb.tsubakuro.sql.TableMetadata;

Expand Down Expand Up @@ -88,29 +89,37 @@ public void onDumpInfo(@Nonnull String tableName, @Nonnull TableMetadata tableIn
.map(TextFormat::shortDebugString)
.collect(Collectors.joining(", "))).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
metadata.append('}');
verbose("found table: table={0}, metadata={1}", tableName, metadata.toString());
verbose("found table: target={0}, metadata={1}", tableName, metadata.toString());
}
}

@Override
public void onDumpInfo(String label, String query, Path dumpDirectory) throws MonitoringException {
Objects.requireNonNull(label);
Objects.requireNonNull(query);
Objects.requireNonNull(dumpDirectory);
verbose("checked query: target={0}, query={1}", label, query);
}

@Override
public void onDumpStart(@Nonnull String tableName, @Nonnull Path dumpDirectory) {
Objects.requireNonNull(tableName);
Objects.requireNonNull(dumpDirectory);
print("table dump operation was started: table={0}, output={1}", tableName, dumpDirectory);
print("dump operation was started: target={0}, output={1}", tableName, dumpDirectory);
}

@Override
public void onDumpFile(@Nonnull String tableName, @Nonnull Path dumpFile) {
Objects.requireNonNull(tableName);
Objects.requireNonNull(dumpFile);
verbose("generated a part of table dump file: table={0}, output={1}", tableName, dumpFile);
verbose("generated a part of dump file: target={0}, output={1}", tableName, dumpFile);
}

@Override
public void onDumpFinish(@Nonnull String tableName, @Nonnull Path dumpDirectory) {
Objects.requireNonNull(tableName);
Objects.requireNonNull(dumpDirectory);
print("table dump operation was finished: table={0}, output={1}", tableName, dumpDirectory);
print("dump operation was finished: target={0}, output={1}", tableName, dumpDirectory);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
import com.tsurugidb.tsubakuro.sql.SqlClient;

/**
* The program entry for Tsurugi Table Dump Tool ({@literal a.k.a.} {@code tgdump}}).
* The program entry for Tsurugi Dump Tool ({@literal a.k.a.} {@code tgdump}}).
* @see CommandArgumentSet
*/
public class Main {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
* CLI classes for Tsurugi Table Dump Tool.
* CLI classes for Tsurugi Dump Tool.
*/
package com.tsurugidb.tools.tgdump.cli;
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
*/
package com.tsurugidb.tools.tgdump.cli;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

import com.tsurugidb.tools.tgdump.core.engine.QueryDumpTargetSelector;
import com.tsurugidb.tools.tgdump.core.engine.TableDumpTargetSelector;

class CommandArgumentSetTest {

@Test
Expand All @@ -36,7 +39,18 @@ void getProfileBundleLoader() {
@Test
void getTargetSelector() {
var args = new CommandArgumentSet();
assertNotNull(args.getTargetSelector());
var selector = args.getTargetSelector();
assertNotNull(selector);
assertInstanceOf(TableDumpTargetSelector.class, selector);
}

@Test
void getTargetSelector_queryMode() {
var args = new CommandArgumentSet();
args.setQueryMode(true);
var selector = args.getTargetSelector();
assertNotNull(selector);
assertInstanceOf(QueryDumpTargetSelector.class, selector);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ void parseArguments_simple() {
assertEquals(URI.create("ipc:testing"), args.getConnectionUri());

// defaults
assertFalse(args.isQueryMode());
assertEquals(Path.of("default"), args.getProfile());
assertNull(args.getConnectionLabel());
assertEquals(0, args.getConnectionTimeoutMillis());
Expand Down Expand Up @@ -292,6 +293,14 @@ void parseArguments_table_missing() {
() -> app.parseArguments("--connection", "ipc:testing", "--to", "output"));
}

@Test
void parseArguments_query() {
var app = new Main();
var args = app.parseArguments("--connection", "ipc:testing", "--sql", "A", "B", "C", "--to", "output");
assertTrue(args.isQueryMode());
assertEquals(List.of("A", "B", "C"), args.getTableNames());
}

@Test
void parseArguments_connection_unsupported() {
var app = new Main();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class BasicDumpMonitor implements DumpMonitor {
public static final String FORMAT_DUMP_INFO = "dump-info";

/**
* The monitoring format name that a table dump was started.
* The monitoring format name that individual dump operations were started.
*/
public static final String FORMAT_DUMP_START = "dump-start";

Expand All @@ -52,15 +52,35 @@ public class BasicDumpMonitor implements DumpMonitor {
public static final String FORMAT_DUMP_FILE = "dump-file";

/**
* The monitoring format name that a table dump was finished.
* The monitoring format name that individual dump operations were finished.
*/
public static final String FORMAT_DUMP_FINISH = "dump-finish";

/**
* The monitoring property of the target type.
*/
public static final String PROPERTY_TYPE = "type";

/**
* The monitoring value of the table type.
*/
public static final String TYPE_TABLE = "table";

/**
* The monitoring value of the query type.
*/
public static final String TYPE_QUERY = "query";

/**
* The monitoring property of the table name.
*/
public static final String PROPERTY_TABLE_NAME = "table";

/**
* The monitoring property of the query text.
*/
public static final String PROPERTY_QUERY_TEXT = "query";

/**
* The monitoring property of the dump destination path.
*/
Expand Down Expand Up @@ -106,6 +126,7 @@ public void onDumpInfo(@Nonnull String tableName, @Nonnull TableMetadata tableIn
Property.of(PROPERTY_COLUMN_TYPE, getTypeName(column))));
}
monitor.onData(FORMAT_DUMP_INFO, List.of(
Property.of(PROPERTY_TYPE, Value.of(TYPE_TABLE)),
Property.of(PROPERTY_TABLE_NAME, Value.of(tableName)),
Property.of(PROPERTY_COLUMNS, Value.of(Array.fromList(columns))),
Property.of(PROPERTY_DESTINATION, Value.of(dumpDirectory.toString()))));
Expand All @@ -122,6 +143,18 @@ private static Value getTypeName(SqlCommon.Column column) {
}
}

@Override
public void onDumpInfo(String label, String query, Path dumpDirectory) throws MonitoringException {
Objects.requireNonNull(label);
Objects.requireNonNull(query);
Objects.requireNonNull(dumpDirectory);
monitor.onData(FORMAT_DUMP_INFO, List.of(
Property.of(PROPERTY_TYPE, Value.of(TYPE_QUERY)),
Property.of(PROPERTY_TABLE_NAME, Value.of(label)),
Property.of(PROPERTY_QUERY_TEXT, Value.of(query)),
Property.of(PROPERTY_DESTINATION, Value.of(dumpDirectory.toString()))));
}

@Override
public void onDumpStart(@Nonnull String tableName, @Nonnull Path dumpDirectory) throws MonitoringException {
Objects.requireNonNull(tableName);
Expand Down
Loading

0 comments on commit 8f8f0e5

Please sign in to comment.