forked from ClickHouse/ClickHouse
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathASTExplainQuery.cpp
More file actions
96 lines (84 loc) · 4.29 KB
/
Copy pathASTExplainQuery.cpp
File metadata and controls
96 lines (84 loc) · 4.29 KB
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
#include <Parsers/ASTExplainQuery.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTSetQuery.h>
#include <Parsers/ASTTableOverrides.h>
#include <Parsers/ASTJSONHelpers.h>
#include <Parsers/ASTJSONReadHelpers.h>
namespace DB
{
namespace ErrorCodes
{
extern const int BAD_ARGUMENTS;
}
void ASTExplainQuery::writeJSON(WriteBuffer & out) const
{
JSONObjectWriter w(out, "ExplainQuery");
w.writeString("kind", toString(kind));
w.writeChild("settings", ast_settings);
w.writeChild("query", query);
w.writeChild("table_function", table_function);
w.writeChild("table_override", table_override);
writeOutputOptionsJSON(w);
}
void ASTExplainQuery::readJSON(const Poco::JSON::Object & json)
{
JSONObjectReader r(json);
kind = fromString(r.getString("kind"));
/// `InterpreterExplainQuery` reads `settings` as an `ASTSetQuery`, the table function as an
/// `ASTFunction`, and the override as an `ASTTableOverride`; restore those with typed reads.
auto settings_child = r.readChildOfType<ASTSetQuery>("settings");
if (settings_child)
setSettings(std::move(settings_child));
auto query_child = r.readChild("query");
if (query_child)
setExplainedQuery(std::move(query_child));
auto table_function_child = r.readChildOfType<ASTFunction>("table_function");
if (table_function_child)
setTableFunction(std::move(table_function_child));
auto table_override_child = r.readChildOfType<ASTTableOverride>("table_override");
if (table_override_child)
setTableOverride(std::move(table_override_child));
/// Enforce the exact parser-produced child set per kind, rejecting forbidden extras as well:
/// `EXPLAIN TABLE OVERRIDE` dereferences the table function and override but never parses an
/// explained query, `EXPLAIN CURRENT TRANSACTION` explains nothing, and every other kind
/// dereferences the explained query (e.g. `dumpAST(*getExplainedQuery())`) and never parses a
/// table function or override. An extra child would format into parser-impossible SQL while
/// `InterpreterExplainQuery` silently ignores it.
switch (kind)
{
case ExplainKind::TableOverride:
if (!getTableFunction() || !getTableOverride())
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"EXPLAIN TABLE OVERRIDE requires 'table_function' and 'table_override' during AST JSON deserialization");
if (getExplainedQuery())
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"EXPLAIN TABLE OVERRIDE cannot carry an explained 'query' during AST JSON deserialization");
/// `ParserExplainQuery` parses the override with `ParserTableOverrideDeclaration(false)`,
/// so it is always the embedded form: not standalone and without a table name. A standalone
/// override would format as `EXPLAIN TABLE OVERRIDE <function> TABLE OVERRIDE name ...`,
/// which the SQL parser can never produce back.
{
const auto & override_ast = getTableOverride()->as<const ASTTableOverride &>();
if (override_ast.is_standalone || !override_ast.table_name.empty())
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"EXPLAIN TABLE OVERRIDE requires an embedded table override (not standalone, without "
"'table_name') during AST JSON deserialization");
}
break;
case ExplainKind::CurrentTransaction:
if (getExplainedQuery() || getTableFunction() || getTableOverride())
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"EXPLAIN CURRENT TRANSACTION cannot carry 'query', 'table_function', or 'table_override' during AST JSON deserialization");
break;
default:
if (!getExplainedQuery())
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"{} requires an explained query during AST JSON deserialization", toString(kind));
if (getTableFunction() || getTableOverride())
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"'table_function' and 'table_override' are only valid for EXPLAIN TABLE OVERRIDE during AST JSON deserialization");
break;
}
readOutputOptionsJSON(r);
}
}