Skip to content

Commit f011612

Browse files
Source command is quiet by default (#175)
## What is the goal of this PR? We make the `source` command not use the pretty-printer or wait for results unless specified with the `--print-answers` flag, which is optional. ## What are the changes implemented in this PR? * `source` now has an optional `--print-answers` * when not printing answers, we execute all the queries in the query string as async queries, then wait for them all at the end * define/undefine never are fully async, and ways do a get() on the query result.
1 parent 47fb7e7 commit f011612

File tree

3 files changed

+137
-58
lines changed

3 files changed

+137
-58
lines changed

TypeDBConsole.java

Lines changed: 102 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.vaticle.typedb.client.api.answer.NumericGroup;
3030
import com.vaticle.typedb.client.api.connection.database.Database;
3131
import com.vaticle.typedb.client.api.connection.user.User;
32+
import com.vaticle.typedb.client.api.query.QueryFuture;
3233
import com.vaticle.typedb.client.common.exception.TypeDBClientException;
3334
import com.vaticle.typedb.common.collection.Either;
3435
import com.vaticle.typedb.common.util.Java;
@@ -72,7 +73,9 @@
7273
import java.util.Iterator;
7374
import java.util.List;
7475
import java.util.Objects;
76+
import java.util.Optional;
7577
import java.util.concurrent.CancellationException;
78+
import java.util.concurrent.CompletableFuture;
7679
import java.util.concurrent.ExecutionException;
7780
import java.util.concurrent.ExecutorService;
7881
import java.util.concurrent.Executors;
@@ -305,9 +308,9 @@ private boolean transactionREPL(TypeDBClient client, String database, TypeDBSess
305308
runClose(tx);
306309
break;
307310
} else if (replCommand.isSource()) {
308-
runSource(tx, replCommand.asSource().file());
311+
runSource(tx, replCommand.asSource().file(), replCommand.asSource().printAnswers());
309312
} else if (replCommand.isQuery()) {
310-
runQuery(tx, replCommand.asQuery().query());
313+
runQueriesPrintAnswers(tx, replCommand.asQuery().query());
311314
}
312315
}
313316
}
@@ -390,10 +393,11 @@ private boolean runInlineCommandMode(CLIOptions options, List<String> inlineComm
390393
runClose(tx);
391394
break;
392395
} else if (txCommand.first().isSource()) {
393-
boolean success = runSource(tx, txCommand.first().asSource().file());
396+
TransactionREPLCommand.Source source = txCommand.first().asSource();
397+
boolean success = runSource(tx, source.file(), source.printAnswers());
394398
if (!success) return false;
395399
} else if (txCommand.first().isQuery()) {
396-
boolean success = runQuery(tx, txCommand.first().asQuery().query());
400+
boolean success = runQueriesPrintAnswers(tx, txCommand.first().asQuery().query());
397401
if (!success) return false;
398402
} else {
399403
printer.error("Command is not available while running console script.");
@@ -579,59 +583,112 @@ private void runClose(TypeDBTransaction tx) {
579583
else printer.info("Transaction closed");
580584
}
581585

582-
private boolean runSource(TypeDBTransaction tx, String file) {
586+
private boolean runSource(TypeDBTransaction tx, String file, boolean printAnswers) {
583587
try {
584588
String queryString = new String(Files.readAllBytes(Paths.get(file)), StandardCharsets.UTF_8);
585-
return runQuery(tx, queryString);
589+
if (printAnswers) return runQueriesPrintAnswers(tx, queryString);
590+
else return runQueries(tx, queryString);
586591
} catch (IOException e) {
587592
printer.error("Failed to open file '" + file + "'");
588593
return false;
589594
}
590595
}
591596

592-
private boolean runQuery(TypeDBTransaction tx, String queryString) {
593-
List<TypeQLQuery> queries;
597+
private boolean runQueries(TypeDBTransaction tx, String queryString) {
598+
Optional<List<TypeQLQuery>> queries = parseQueries(queryString);
599+
if (!queries.isPresent()) return false;
600+
CompletableFuture.allOf(queries.get().stream().map(query -> runQuery(tx, query))
601+
.toArray(CompletableFuture[]::new)).join();
602+
return true;
603+
}
604+
605+
private boolean runQueriesPrintAnswers(TypeDBTransaction tx, String queryString) {
606+
Optional<List<TypeQLQuery>> queries = parseQueries(queryString);
607+
if (!queries.isPresent()) return false;
608+
queries.get().forEach(query -> runQueryPrintAnswers(tx, query));
609+
return true;
610+
}
611+
612+
@SuppressWarnings("CheckReturnValue")
613+
private CompletableFuture<Void> runQuery(TypeDBTransaction tx, TypeQLQuery query) {
614+
if (query instanceof TypeQLDefine) {
615+
tx.query().define(query.asDefine()).get();
616+
printer.info("Concepts have been defined");
617+
return CompletableFuture.completedFuture(null);
618+
} else if (query instanceof TypeQLUndefine) {
619+
tx.query().undefine(query.asUndefine()).get();
620+
printer.info("Concepts have been undefined");
621+
return CompletableFuture.completedFuture(null);
622+
} else if (query instanceof TypeQLInsert) {
623+
Stream<ConceptMap> result = tx.query().insert(query.asInsert());
624+
return CompletableFuture.runAsync(result::findFirst);
625+
} else if (query instanceof TypeQLDelete) {
626+
QueryFuture<Void> deleteFuture = tx.query().delete(query.asDelete());
627+
return CompletableFuture.runAsync(deleteFuture::get);
628+
} else if (query instanceof TypeQLUpdate) {
629+
Stream<ConceptMap> result = tx.query().update(query.asUpdate());
630+
return CompletableFuture.runAsync(result::findFirst);
631+
} else if (query instanceof TypeQLMatch) {
632+
Stream<ConceptMap> result = tx.query().match(query.asMatch());
633+
return CompletableFuture.runAsync(result::findFirst);
634+
} else if (query instanceof TypeQLMatch.Aggregate) {
635+
QueryFuture<Numeric> answerFuture = tx.query().match(query.asMatchAggregate());
636+
return CompletableFuture.runAsync(answerFuture::get);
637+
} else if (query instanceof TypeQLMatch.Group) {
638+
Stream<ConceptMapGroup> result = tx.query().match(query.asMatchGroup());
639+
return CompletableFuture.runAsync(result::findFirst);
640+
} else if (query instanceof TypeQLMatch.Group.Aggregate) {
641+
Stream<NumericGroup> result = tx.query().match(query.asMatchGroupAggregate());
642+
return CompletableFuture.runAsync(result::findFirst);
643+
} else if (query instanceof TypeQLCompute) {
644+
throw new TypeDBConsoleException("Compute query is not yet supported");
645+
} else {
646+
throw new TypeDBConsoleException("Query is of unrecognized type: " + query);
647+
}
648+
}
649+
650+
private void runQueryPrintAnswers(TypeDBTransaction tx, TypeQLQuery query) {
651+
if (query instanceof TypeQLDefine) {
652+
tx.query().define(query.asDefine()).get();
653+
printer.info("Concepts have been defined");
654+
} else if (query instanceof TypeQLUndefine) {
655+
tx.query().undefine(query.asUndefine()).get();
656+
printer.info("Concepts have been undefined");
657+
} else if (query instanceof TypeQLInsert) {
658+
Stream<ConceptMap> result = tx.query().insert(query.asInsert());
659+
printCancellableResult(result, x -> printer.conceptMap(x, tx));
660+
} else if (query instanceof TypeQLDelete) {
661+
tx.query().delete(query.asDelete()).get();
662+
printer.info("Concepts have been deleted");
663+
} else if (query instanceof TypeQLUpdate) {
664+
Stream<ConceptMap> result = tx.query().update(query.asUpdate());
665+
printCancellableResult(result, x -> printer.conceptMap(x, tx));
666+
} else if (query instanceof TypeQLMatch) {
667+
Stream<ConceptMap> result = tx.query().match(query.asMatch());
668+
printCancellableResult(result, x -> printer.conceptMap(x, tx));
669+
} else if (query instanceof TypeQLMatch.Aggregate) {
670+
QueryFuture<Numeric> answerFuture = tx.query().match(query.asMatchAggregate());
671+
printer.numeric(answerFuture.get());
672+
} else if (query instanceof TypeQLMatch.Group) {
673+
Stream<ConceptMapGroup> result = tx.query().match(query.asMatchGroup());
674+
printCancellableResult(result, x -> printer.conceptMapGroup(x, tx));
675+
} else if (query instanceof TypeQLMatch.Group.Aggregate) {
676+
Stream<NumericGroup> result = tx.query().match(query.asMatchGroupAggregate());
677+
printCancellableResult(result, x -> printer.numericGroup(x, tx));
678+
} else if (query instanceof TypeQLCompute) {
679+
throw new TypeDBConsoleException("Compute query is not yet supported");
680+
} else {
681+
throw new TypeDBConsoleException("Query is of unrecognized type: " + query);
682+
}
683+
}
684+
685+
Optional<List<TypeQLQuery>> parseQueries(String queryString) {
594686
try {
595-
queries = TypeQL.parseQueries(queryString).collect(toList());
687+
return Optional.of(TypeQL.parseQueries(queryString).collect(toList()));
596688
} catch (TypeQLException e) {
597689
printer.error(e.getMessage());
598-
return false;
690+
return Optional.empty();
599691
}
600-
for (TypeQLQuery query : queries) {
601-
if (query instanceof TypeQLDefine) {
602-
tx.query().define(query.asDefine()).get();
603-
printer.info("Concepts have been defined");
604-
} else if (query instanceof TypeQLUndefine) {
605-
tx.query().undefine(query.asUndefine()).get();
606-
printer.info("Concepts have been undefined");
607-
} else if (query instanceof TypeQLInsert) {
608-
Stream<ConceptMap> result = tx.query().insert(query.asInsert());
609-
printCancellableResult(result, x -> printer.conceptMap(x, tx));
610-
} else if (query instanceof TypeQLDelete) {
611-
tx.query().delete(query.asDelete()).get();
612-
printer.info("Concepts have been deleted");
613-
} else if (query instanceof TypeQLUpdate) {
614-
Stream<ConceptMap> result = tx.query().update(query.asUpdate());
615-
printCancellableResult(result, x -> printer.conceptMap(x, tx));
616-
} else if (query instanceof TypeQLMatch) {
617-
Stream<ConceptMap> result = tx.query().match(query.asMatch());
618-
printCancellableResult(result, x -> printer.conceptMap(x, tx));
619-
} else if (query instanceof TypeQLMatch.Aggregate) {
620-
Numeric answer = tx.query().match(query.asMatchAggregate()).get();
621-
printer.numeric(answer);
622-
} else if (query instanceof TypeQLMatch.Group) {
623-
Stream<ConceptMapGroup> result = tx.query().match(query.asMatchGroup());
624-
printCancellableResult(result, x -> printer.conceptMapGroup(x, tx));
625-
} else if (query instanceof TypeQLMatch.Group.Aggregate) {
626-
Stream<NumericGroup> result = tx.query().match(query.asMatchGroupAggregate());
627-
printCancellableResult(result, x -> printer.numericGroup(x, tx));
628-
} else if (query instanceof TypeQLCompute) {
629-
throw new TypeDBConsoleException("Compute query is not yet supported");
630-
} else {
631-
throw new TypeDBConsoleException("Query is of unrecognized type: " + query);
632-
}
633-
}
634-
return true;
635692
}
636693

637694
private <T> void printCancellableResult(Stream<T> results, Consumer<T> printFn) {

command/TransactionREPLCommand.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@
2828
import java.util.ArrayList;
2929
import java.util.Arrays;
3030
import java.util.List;
31+
import java.util.Set;
3132

3233
import static com.vaticle.typedb.common.collection.Collections.pair;
34+
import static com.vaticle.typedb.common.collection.Collections.set;
3335
import static com.vaticle.typedb.console.common.exception.ErrorMessage.Internal.ILLEGAL_CAST;
3436
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_CLEAR_ARGS;
3537
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_CLOSE_ARGS;
3638
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_COMMIT_ARGS;
3739
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_EXIT_ARGS;
3840
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_HELP_ARGS;
41+
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_OPTIONAL_ARG;
3942
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_ROLLBACK_ARGS;
4043
import static com.vaticle.typedb.console.common.exception.ErrorMessage.TransactionRepl.INVALID_SOURCE_ARGS;
4144

@@ -216,20 +219,27 @@ public TransactionREPLCommand.Close asClose() {
216219
class Source implements TransactionREPLCommand {
217220

218221
private static final String token = "source";
219-
private static final String helpCommand = token + " <file>";
220-
private static final String description = "Run TypeQL queries in file";
221-
private static final int args = 1;
222+
private static final String helpCommand = token + " <file> [--print-answers]";
223+
private static final String description = "Run TypeQL queries in file.";
224+
private static final Set<String> optionalArgs = set("--print-answers");
225+
private static final int mandatoryArgs = 1;
222226

223227
private final String file;
228+
private final boolean printAnswers;
224229

225-
public Source(String file) {
230+
public Source(String file, boolean printAnswers) {
226231
this.file = file;
232+
this.printAnswers = printAnswers;
227233
}
228234

229235
public String file() {
230236
return file;
231237
}
232238

239+
public boolean printAnswers() {
240+
return printAnswers;
241+
}
242+
233243
@Override
234244
public boolean isSource() {
235245
return true;
@@ -316,9 +326,18 @@ static Either<TransactionREPLCommand, String> readCommand(String line) {
316326
if (tokens.length - 1 != Close.args) return Either.second(INVALID_CLOSE_ARGS.message(Close.args, tokens.length - 1));
317327
command = new Close();
318328
} else if (tokens[0].equals(Source.token)) {
319-
if (tokens.length - 1 != Source.args) return Either.second(INVALID_SOURCE_ARGS.message(Source.args, tokens.length - 1));
329+
int args = tokens.length - 1;
330+
boolean printAnswers = false;
331+
if (args < Source.mandatoryArgs || args > Source.mandatoryArgs + Source.optionalArgs.size()) {
332+
return Either.second(INVALID_SOURCE_ARGS.message(Source.mandatoryArgs, Source.optionalArgs.size(), args));
333+
} else if (tokens.length == 3) {
334+
String printAnswersArg = tokens[2];
335+
if (!Source.optionalArgs.contains(printAnswersArg)) {
336+
return Either.second(INVALID_OPTIONAL_ARG.message(Source.token, printAnswersArg));
337+
} else printAnswers = true;
338+
}
320339
String file = tokens[1];
321-
command = new Source(file);
340+
command = new Source(file, printAnswers);
322341
} else {
323342
command = new Query(line);
324343
}

common/exception/ErrorMessage.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,23 @@ private ErrorMessage(String codePrefix, int codeNumber, String messagePrefix, St
2525

2626
public static class TransactionRepl extends ErrorMessage {
2727

28+
public static final TransactionRepl INVALID_OPTIONAL_ARG =
29+
new TransactionRepl(1, "'%s' does not have an optional argument '%s'.");
2830
public static final TransactionRepl INVALID_EXIT_ARGS =
29-
new TransactionRepl(1, "'exit' expects %s space-separated arguments, received %s.");
31+
new TransactionRepl(2, "'exit' expects %s space-separated arguments, received %s.");
3032
public static final TransactionRepl INVALID_HELP_ARGS =
31-
new TransactionRepl(2, "'help' expects %s space-separated arguments, received %s.");
33+
new TransactionRepl(3, "'help' expects %s space-separated arguments, received %s.");
3234
public static final TransactionRepl INVALID_CLEAR_ARGS =
33-
new TransactionRepl(3, "'clear' expects %s space-separated arguments, received %s.");
35+
new TransactionRepl(4, "'clear' expects %s space-separated arguments, received %s.");
3436
public static final TransactionRepl INVALID_COMMIT_ARGS =
35-
new TransactionRepl(4, "'commit' expects %s space-separated arguments, received %s.");
37+
new TransactionRepl(5, "'commit' expects %s space-separated arguments, received %s.");
3638
public static final TransactionRepl INVALID_ROLLBACK_ARGS =
37-
new TransactionRepl(5, "'rollback' expects %s space-separated arguments, received %s.");
39+
new TransactionRepl(6, "'rollback' expects %s space-separated arguments, received %s.");
3840
public static final TransactionRepl INVALID_CLOSE_ARGS =
39-
new TransactionRepl(6, "'close' expects %s space-separated arguments, received %s.");
41+
new TransactionRepl(7, "'close' expects %s space-separated arguments, received %s.");
4042
public static final TransactionRepl INVALID_SOURCE_ARGS =
41-
new TransactionRepl(7, "'source' expects %s space-separated arguments, received %s.");
43+
new TransactionRepl(8, "'source' expects %s mandatory arguments and up to %s optional " +
44+
"arguments, received %s arguments.");
4245

4346
private static final String codePrefix = "TXN";
4447
private static final String messagePrefix = "Invalid Transaction command";

0 commit comments

Comments
 (0)