1 | #include <DataTypes/DataTypesNumber.h> |
2 | |
3 | #include <Storages/System/StorageSystemOne.h> |
4 | #include <Storages/System/StorageSystemNumbers.h> |
5 | #include <Databases/DatabaseMemory.h> |
6 | |
7 | #include <Parsers/ParserSelectQuery.h> |
8 | #include <Parsers/parseQuery.h> |
9 | |
10 | #include <Interpreters/Context.h> |
11 | #include <Interpreters/SyntaxAnalyzer.h> |
12 | |
13 | #include <IO/WriteBufferFromFileDescriptor.h> |
14 | #include <IO/ReadBufferFromFileDescriptor.h> |
15 | |
16 | #include <vector> |
17 | #include <unordered_map> |
18 | #include <iostream> |
19 | |
20 | |
21 | using namespace DB; |
22 | |
23 | namespace DB |
24 | { |
25 | namespace ErrorCodes |
26 | { |
27 | extern const int SYNTAX_ERROR; |
28 | } |
29 | } |
30 | |
31 | struct TestEntry |
32 | { |
33 | String query; |
34 | std::unordered_map<String, String> expected_aliases; /// alias -> AST.getID() |
35 | NamesAndTypesList source_columns = {}; |
36 | Names required_result_columns = {}; |
37 | |
38 | bool check(const Context & context) |
39 | { |
40 | ASTPtr ast = parse(query); |
41 | |
42 | auto res = SyntaxAnalyzer(context, {}).analyze(ast, source_columns, required_result_columns); |
43 | return checkAliases(*res); |
44 | } |
45 | |
46 | private: |
47 | bool checkAliases(const SyntaxAnalyzerResult & res) |
48 | { |
49 | for (const auto & alias : res.aliases) |
50 | { |
51 | const String & alias_name = alias.first; |
52 | if (expected_aliases.count(alias_name) == 0 || |
53 | expected_aliases[alias_name] != alias.second->getID()) |
54 | { |
55 | std::cout << "unexpected alias: " << alias_name << ' ' << alias.second->getID() << std::endl; |
56 | return false; |
57 | } |
58 | else |
59 | expected_aliases.erase(alias_name); |
60 | } |
61 | |
62 | if (!expected_aliases.empty()) |
63 | { |
64 | std::cout << "missing aliases: " << expected_aliases.size() << std::endl; |
65 | return false; |
66 | } |
67 | |
68 | return true; |
69 | } |
70 | |
71 | static ASTPtr parse(const std::string & query) |
72 | { |
73 | ParserSelectQuery parser; |
74 | std::string message; |
75 | auto text = query.data(); |
76 | if (ASTPtr ast = tryParseQuery(parser, text, text + query.size(), message, false, "" , false, 0)) |
77 | return ast; |
78 | throw Exception(message, ErrorCodes::SYNTAX_ERROR); |
79 | } |
80 | }; |
81 | |
82 | |
83 | int main() |
84 | { |
85 | std::vector<TestEntry> queries = |
86 | { |
87 | { |
88 | "SELECT number AS n FROM system.numbers LIMIT 0" , |
89 | {{"n" , "Identifier_number" }}, |
90 | { NameAndTypePair("number" , std::make_shared<DataTypeUInt64>()) } |
91 | }, |
92 | |
93 | { |
94 | "SELECT number AS n FROM system.numbers LIMIT 0" , |
95 | {{"n" , "Identifier_number" }} |
96 | } |
97 | }; |
98 | |
99 | Context context = Context::createGlobal(); |
100 | context.makeGlobalContext(); |
101 | |
102 | auto system_database = std::make_shared<DatabaseMemory>("system" ); |
103 | context.addDatabase("system" , system_database); |
104 | //context.setCurrentDatabase("system"); |
105 | system_database->attachTable("one" , StorageSystemOne::create("one" )); |
106 | system_database->attachTable("numbers" , StorageSystemNumbers::create("numbers" , false)); |
107 | |
108 | size_t success = 0; |
109 | for (auto & entry : queries) |
110 | { |
111 | try |
112 | { |
113 | if (entry.check(context)) |
114 | { |
115 | ++success; |
116 | std::cout << "[OK] " << entry.query << std::endl; |
117 | } |
118 | else |
119 | std::cout << "[Failed] " << entry.query << std::endl; |
120 | } |
121 | catch (Exception & e) |
122 | { |
123 | std::cout << "[Error] " << entry.query << std::endl << e.displayText() << std::endl; |
124 | } |
125 | } |
126 | |
127 | return success != queries.size(); |
128 | } |
129 | |