Fix EXPLAIN ANALYZE exec when query returns no cols (#4672)

We do not include dummy column if original task didn't return any
columns.
Otherwise, number of columns that original task returned wouldn't
match number of columns returned by worker_save_query_explain_analyze.
pull/4677/head
Onur Tirtir 2021-02-10 17:59:47 +03:00 committed by GitHub
parent 29d340331e
commit 9f619a85d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 118 additions and 1 deletions

View File

@ -1512,8 +1512,16 @@ WrapQueryForExplainAnalyze(const char *queryString, TupleDesc tupleDesc)
ExplainFormatStr(CurrentDistributedQueryExplainOptions.format));
StringInfo wrappedQuery = makeStringInfo();
/*
* We do not include dummy column if original query didn't return any columns.
* Otherwise, number of columns that original query returned wouldn't match
* number of columns returned by worker_save_query_explain_analyze.
*/
char *workerSaveQueryFetchCols = (tupleDesc->natts == 0) ? "" : "*";
appendStringInfo(wrappedQuery,
"SELECT * FROM worker_save_query_explain_analyze(%s, %s) AS (%s)",
"SELECT %s FROM worker_save_query_explain_analyze(%s, %s) AS (%s)",
workerSaveQueryFetchCols,
quote_literal_cstr(queryString),
quote_literal_cstr(explainOptions->data),
columnDef->data);

View File

@ -2956,3 +2956,78 @@ Custom Scan (Citus Adaptive) (actual rows=1 loops=1)
-- reset back
reset citus.explain_analyze_sort_method;
DROP TABLE explain_analyze_execution_time;
CREATE SCHEMA multi_explain;
SET search_path TO multi_explain;
-- test EXPLAIN ANALYZE when original query returns no columns
CREATE TABLE reference_table(a int);
SELECT create_reference_table('reference_table');
INSERT INTO reference_table VALUES (1);
EXPLAIN :default_analyze_flags SELECT FROM reference_table;
Custom Scan (Citus Adaptive) (actual rows=1 loops=1)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Seq Scan on reference_table_570031 reference_table (actual rows=1 loops=1)
CREATE TABLE distributed_table_1(a int, b int);
SELECT create_distributed_table('distributed_table_1','a');
INSERT INTO distributed_table_1 values (1,1);
EXPLAIN :default_analyze_flags SELECT row_number() OVER() AS r FROM distributed_table_1;
WindowAgg (actual rows=1 loops=1)
-> Custom Scan (Citus Adaptive) (actual rows=1 loops=1)
Task Count: 2
Tasks Shown: One of 2
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Seq Scan on distributed_table_1_570032 distributed_table_xxx (actual rows=1 loops=1)
CREATE TABLE distributed_table_2(a int, b int);
SELECT create_distributed_table('distributed_table_2','a');
INSERT INTO distributed_table_2 VALUES (1,1);
EXPLAIN :default_analyze_flags
WITH r AS (SELECT row_number() OVER () AS r FROM distributed_table_1)
SELECT * FROM distributed_table_2
JOIN r ON (r = distributed_table_2.b)
LIMIT 3;
Limit (actual rows=1 loops=1)
-> Custom Scan (Citus Adaptive) (actual rows=1 loops=1)
-> Distributed Subplan XXX_1
Intermediate Data Size: 14 bytes
Result destination: Send to 2 nodes
-> WindowAgg (actual rows=1 loops=1)
-> Custom Scan (Citus Adaptive) (actual rows=1 loops=1)
Task Count: 2
Tasks Shown: One of 2
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Seq Scan on distributed_table_1_570032 distributed_table_xxx (actual rows=1 loops=1)
Task Count: 2
Tuple data received from nodes: 3 bytes
Tasks Shown: One of 2
-> Task
Tuple data received from node: 3 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Limit (actual rows=1 loops=1)
-> Nested Loop (actual rows=1 loops=1)
Join Filter: (distributed_table_2.b = intermediate_result.r)
-> Function Scan on read_intermediate_result intermediate_result (actual rows=1 loops=1)
-> Seq Scan on distributed_table_2_570034 distributed_table_xxx (actual rows=1 loops=1)
EXPLAIN :default_analyze_flags SELECT FROM (SELECT * FROM reference_table) subquery;
Custom Scan (Citus Adaptive) (actual rows=1 loops=1)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Seq Scan on reference_table_570031 reference_table (actual rows=1 loops=1)
PREPARE dummy_prep_stmt(int) AS SELECT FROM distributed_table_1;
EXPLAIN :default_analyze_flags EXECUTE dummy_prep_stmt(50);
Custom Scan (Citus Adaptive) (actual rows=1 loops=1)
Task Count: 2
Tasks Shown: One of 2
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Seq Scan on distributed_table_1_570032 distributed_table_xxx (actual rows=1 loops=1)
SET client_min_messages TO ERROR;
DROP SCHEMA multi_explain CASCADE;

View File

@ -1052,3 +1052,37 @@ EXPLAIN (COSTS FALSE, ANALYZE TRUE, TIMING FALSE, SUMMARY FALSE) select a, CASE
-- reset back
reset citus.explain_analyze_sort_method;
DROP TABLE explain_analyze_execution_time;
CREATE SCHEMA multi_explain;
SET search_path TO multi_explain;
-- test EXPLAIN ANALYZE when original query returns no columns
CREATE TABLE reference_table(a int);
SELECT create_reference_table('reference_table');
INSERT INTO reference_table VALUES (1);
EXPLAIN :default_analyze_flags SELECT FROM reference_table;
CREATE TABLE distributed_table_1(a int, b int);
SELECT create_distributed_table('distributed_table_1','a');
INSERT INTO distributed_table_1 values (1,1);
EXPLAIN :default_analyze_flags SELECT row_number() OVER() AS r FROM distributed_table_1;
CREATE TABLE distributed_table_2(a int, b int);
SELECT create_distributed_table('distributed_table_2','a');
INSERT INTO distributed_table_2 VALUES (1,1);
EXPLAIN :default_analyze_flags
WITH r AS (SELECT row_number() OVER () AS r FROM distributed_table_1)
SELECT * FROM distributed_table_2
JOIN r ON (r = distributed_table_2.b)
LIMIT 3;
EXPLAIN :default_analyze_flags SELECT FROM (SELECT * FROM reference_table) subquery;
PREPARE dummy_prep_stmt(int) AS SELECT FROM distributed_table_1;
EXPLAIN :default_analyze_flags EXECUTE dummy_prep_stmt(50);
SET client_min_messages TO ERROR;
DROP SCHEMA multi_explain CASCADE;