-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix trino-cli to display plans for EXPLAIN ANALYZE for update statements #13907
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -162,8 +162,12 @@ private boolean renderQueryOutput(Terminal terminal, PrintStream out, PrintStrea | |
if (client.isRunning() || (client.isFinished() && client.finalStatusInfo().getError() == null)) { | ||
QueryStatusInfo results = client.isRunning() ? client.currentStatusInfo() : client.finalStatusInfo(); | ||
if (results.getUpdateType() != null) { | ||
renderUpdate(errorChannel, results); | ||
renderUpdate(errorChannel, results, outputFormat, usePager); | ||
} | ||
// TODO once https://github.com/trinodb/trino/issues/14253 is done this else here should be needed | ||
// and should be replaced with just simple: | ||
// if there is updateCount print it | ||
// if there are columns(resultSet) then print it | ||
else if (results.getColumns() == null) { | ||
errorChannel.printf("Query %s has no columns\n", results.getId()); | ||
return false; | ||
|
@@ -220,14 +224,21 @@ private void processInitialStatusUpdates(WarningsPrinter warningsPrinter) | |
warningsPrinter.print(warnings, false, true); | ||
} | ||
|
||
private void renderUpdate(PrintStream out, QueryStatusInfo results) | ||
private void renderUpdate(PrintStream out, QueryStatusInfo results, OutputFormat outputFormat, boolean usePager) | ||
{ | ||
String status = results.getUpdateType(); | ||
if (results.getUpdateCount() != null) { | ||
long count = results.getUpdateCount(); | ||
status += format(": %s row%s", count, (count != 1) ? "s" : ""); | ||
out.println(status); | ||
} | ||
else if (results.getColumns() != null && !results.getColumns().isEmpty()) { | ||
out.println(status); | ||
renderResults(out, outputFormat, usePager, results.getColumns()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why go here only when updateCount is null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for example -- after this change -- for CTAS we print number of rows written:
but for EXPLAIN ANALYZE CTAS we print only the operation name "CREATE TABLE", without the row count:
The query plan is correctly printed, but row count should be too There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will add a code comment, mainly to avoid printing same information twice as in your comment above #13907 (comment) |
||
} | ||
else { | ||
out.println(status); | ||
} | ||
out.println(status); | ||
discardResults(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should still be called but after the call to both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm ok, I will give it a look thanks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nineinchnick after There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @nineinchnick thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed |
||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,7 +49,6 @@ | |
import io.trino.spi.block.BlockEncodingSerde; | ||
import io.trino.spi.exchange.ExchangeId; | ||
import io.trino.spi.security.SelectedRole; | ||
import io.trino.spi.type.BooleanType; | ||
import io.trino.spi.type.Type; | ||
import io.trino.transaction.TransactionId; | ||
|
||
|
@@ -507,13 +506,11 @@ private synchronized QueryResults getNextResult(long token, UriInfo uriInfo, Dat | |
|
||
private synchronized QueryResultRows removePagesFromExchange(QueryInfo queryInfo, long targetResultBytes) | ||
{ | ||
// For queries with no output, return a fake boolean result for clients that require it. | ||
if (!resultsConsumed && queryInfo.getOutputStage().isEmpty()) { | ||
return queryResultRowsBuilder(session) | ||
.withSingleBooleanValue(createColumn("result", BooleanType.BOOLEAN, supportsParametricDateTime), true) | ||
.withColumnsAndTypes(ImmutableList.of(), ImmutableList.of()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to make sure, could this affect older versions of Trino CLI or other clients? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the changes in the Trino CLI don't require these, should they be in separate commits? If they do, would the Trino CLI still work correctly with older Trino servers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we run tests against older versions and they work so I think we are fine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does seems to affect other clients though probably - see trinodb/trino-python-client#212 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, PR title could be probably better worded (and release notes as well) to mention we no longer return result sets for queries which don't return output (which is correct behaviour but older code could be relying on this). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No problem. The comment was meant more to the reviewers. Thanks for the offer - if you want to and feel comfortable with that sure but don't feel responsible for it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc: @findepi probably There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel responsible but not comfortable, what should I do in such a case ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hashhar you know i strive to make PR titles as informative as I can be, but it's also not possible to fit the whole story in that line Would it make sense to have some Python client comaptibility smoke tests within this repo? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No problem. I'd request a review to make sure you can verify the functional changes there match what we did for the JDBC client here. @homar
@findepi The Python client isn't my biggest concern - my main concern is this is a user-facing change where if someone wrote code relying on DDL queries as well returning results then they'd be affected (even though it'd be wrong to rely on that in the first place). We can consider adding a smoke test here that tests current server against current client only so that at least we can ensure that there's at-least 1 working Python (and Go) client for each Trino server release. I'll create a separate issue about such tests and let's continue here. |
||
.build(); | ||
} | ||
|
||
// Remove as many pages as possible from the exchange until just greater than DESIRED_RESULT_BYTES | ||
// NOTE: it is critical that query results are created for the pages removed from the exchange | ||
// client while holding the lock because the query may transition to the finished state when the | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -403,6 +403,30 @@ public void testSetRole() | |||||
assertThat(trimLines(trino.readLinesUntilPrompt())).doesNotContain("admin"); | ||||||
} | ||||||
|
||||||
@Test(groups = CLI, timeOut = TIMEOUT) | ||||||
public void shouldPrintExplainAnalyzePlan() | ||||||
throws Exception | ||||||
{ | ||||||
launchTrinoCliWithServerArgument(); | ||||||
trino.waitForPrompt(); | ||||||
trino.getProcessInput().println("EXPLAIN ANALYZE CREATE TABLE iceberg.default.test_table AS SELECT * FROM hive.default.nation LIMIT 10;"); | ||||||
List<String> lines = trimLines(trino.readLinesUntilPrompt()); | ||||||
// TODO once https://github.com/trinodb/trino/issues/14253 is done this should be assertThat(lines).contains("CREATE TABLE: 1 row", "Query Plan"); | ||||||
assertThat(lines).contains("CREATE TABLE", "Query Plan"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is hard to do it now due to #14253, but that could be a good enhancement for the future |
||||||
// TODO once https://github.com/trinodb/trino/issues/14253 is done this should be assertThat(lines).contains("INSERT: 1 row", "Query Plan"); | ||||||
trino.getProcessInput().println("EXPLAIN ANALYZE INSERT INTO iceberg.default.test_table VALUES(100, 'URUGUAY', 3, 'test comment');"); | ||||||
lines = trimLines(trino.readLinesUntilPrompt()); | ||||||
assertThat(lines).contains("INSERT", "Query Plan"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is hard to do it now due to #14253, but that could be a good enhancement for the future |
||||||
// TODO once https://github.com/trinodb/trino/issues/14253 is done this should be assertThat(lines).contains("UPDATE: 1 row", "Query Plan"); | ||||||
trino.getProcessInput().println("EXPLAIN ANALYZE UPDATE iceberg.default.test_table SET n_comment = 'testValue 5' WHERE n_nationkey = 100;"); | ||||||
lines = trimLines(trino.readLinesUntilPrompt()); | ||||||
assertThat(lines).contains("UPDATE", "Query Plan"); | ||||||
// TODO once https://github.com/trinodb/trino/issues/14253 is done this should be assertThat(lines).contains("DELETE: 1 row", "Query Plan"); | ||||||
trino.getProcessInput().println("EXPLAIN ANALYZE DELETE FROM iceberg.default.test_table WHERE n_nationkey = 100;"); | ||||||
lines = trimLines(trino.readLinesUntilPrompt()); | ||||||
assertThat(lines).contains("DELETE", "Query Plan"); | ||||||
} | ||||||
|
||||||
private void launchTrinoCliWithServerArgument(String... arguments) | ||||||
throws IOException | ||||||
{ | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the server not set the update type in results if it's an explain query?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this, see my comment below with link to a pr that has links to 2 others :D I did 3 different approaches but none of them seems good enough