-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathTableFunctionExplain.cpp
109 lines (93 loc) · 3.8 KB
/
TableFunctionExplain.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <Interpreters/InterpreterSelectWithUnionQuery.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTSelectWithUnionQuery.h>
#include <Parsers/queryToString.h>
#include <Storages/StorageValues.h>
#include <TableFunctions/ITableFunction.h>
#include <TableFunctions/TableFunctionFactory.h>
#include <TableFunctions/TableFunctionExplain.h>
#include <TableFunctions/registerTableFunctions.h>
#include <Processors/Executors/PullingPipelineExecutor.h>
namespace DB
{
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
extern const int BAD_ARGUMENTS;
}
void TableFunctionExplain::parseArguments(const ASTPtr & ast_function, ContextPtr /*context*/)
{
const auto * function = ast_function->as<ASTFunction>();
if (function && function->arguments && function->arguments->children.size() == 1)
{
const auto & query_arg = function->arguments->children[0];
if (!query_arg->as<ASTExplainQuery>())
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"Table function '{}' requires a explain query argument, got '{}'",
getName(), queryToString(query_arg));
query = query_arg;
}
else
{
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"Table function '{}' cannot be called directly, use `SELECT * FROM (EXPLAIN ...)` syntax", getName());
}
}
ColumnsDescription TableFunctionExplain::getActualTableStructure(ContextPtr context) const
{
Block sample_block = getInterpreter(context).getSampleBlock(query->as<ASTExplainQuery>()->getKind());
ColumnsDescription columns_description;
for (const auto & column : sample_block.getColumnsWithTypeAndName())
columns_description.add(ColumnDescription(column.name, column.type));
return columns_description;
}
static Block executeMonoBlock(QueryPipeline & pipeline)
{
if (!pipeline.pulling())
throw Exception(ErrorCodes::LOGICAL_ERROR, "Expected pulling pipeline");
PullingPipelineExecutor pulling_executor(pipeline);
std::vector<Block> blocks;
while (true)
{
Block block;
if (pulling_executor.pull(block))
blocks.push_back(std::move(block));
else
break;
}
if (blocks.size() == 1)
return blocks[0];
return concatenateBlocks(blocks);
}
StoragePtr TableFunctionExplain::executeImpl(
const ASTPtr & /*ast_function*/, ContextPtr context, const std::string & table_name, ColumnsDescription /*cached_columns*/) const
{
BlockIO blockio = getInterpreter(context).execute();
Block block = executeMonoBlock(blockio.pipeline);
StorageID storage_id(getDatabaseName(), table_name);
/// proton: start cannot directly make shared DataTypePtr and StorageValues::create is the only way to do it
auto storage = StorageValues::create(storage_id,getActualTableStructure(context),std::move(block));
/// proton: end
storage->startup();
return storage;
}
InterpreterExplainQuery TableFunctionExplain::getInterpreter(ContextPtr context) const
{
if (!query)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Table function '{}' requires a explain query argument", getName());
return InterpreterExplainQuery(query, context);
}
void registerTableFunctionExplain(TableFunctionFactory & factory)
{
factory.registerFunction<TableFunctionExplain>({.documentation = {
.description=R"(
Returns result of EXPLAIN query.
The function should not be called directly but can be invoked via `SELECT * FROM (EXPLAIN <query>)`.
You can use this query to process the result of EXPLAIN further using SQL (e.g., in tests).
Example:
[example:1]
)",
.examples={{"1", "SELECT explain FROM (EXPLAIN AST SELECT * FROM system.numbers) WHERE explain LIKE '%Asterisk%'", ""}}
}});
}
}