-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathsystem_view_definition_impl.h
282 lines (224 loc) · 8.82 KB
/
system_view_definition_impl.h
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/* Copyright (c) 2017, 2025, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef DD_SYSTEM_VIEWS__SYSTEM_VIEW_DEFINITION_IMPL_INCLUDED
#define DD_SYSTEM_VIEWS__SYSTEM_VIEW_DEFINITION_IMPL_INCLUDED
#include <map>
#include <memory>
#include <vector>
#include "sql/dd/string_type.h" // dd::String_type
#include "sql/dd/types/system_view_definition.h" // dd::System_view_definition
#include "sql/mysqld.h" // lower_case_table_names
namespace dd {
namespace system_views {
class System_view_definition_impl : public System_view_definition {
public:
/**
Get view name.
@return name of the view.
*/
virtual const String_type &view_name() const { return m_view_name; }
/**
Set view name.
*/
virtual void set_view_name(const String_type &name) { m_view_name = name; }
/**
Get collation clause to append to view definition for some
view columns based on lower_case_table_names.
@return Empty string if lctn=0, other wise " COLLATE utf8mb3_tolower_ci".
*/
static const String_type fs_name_collation() {
if (lower_case_table_names != 0) return " COLLATE utf8mb3_tolower_ci";
return "";
}
String_type build_ddl_create_view() const override = 0;
private:
// Name of I_S system view;
String_type m_view_name;
};
class System_view_select_definition_impl : public System_view_definition_impl {
public:
/**
Add a field definition for the SELECT projection.
This function can be called more than once. The call will add a new
projection to the SELECT command.
@param field_number Ordinal position of field in the projection list.
@param field_name Field name used for the SELECT's projection.
@param field_definition Expression representing the projection.
@param add_quotes If true, output single quotes around the
field_definition.
*/
virtual void add_field(int field_number, const String_type &field_name,
const String_type &field_definition,
bool add_quotes = false) {
// Make sure the field_number and field_name are not added twise.
assert(m_field_numbers.find(field_name) == m_field_numbers.end() &&
m_field_definitions.find(field_number) == m_field_definitions.end());
// Store the field number.
m_field_numbers[field_name] = field_number;
// Store the field definition expression.
Stringstream_type ss;
if (field_name == "*") {
ss << " * ";
} else {
if (add_quotes) {
assert(field_definition.find('\'') == String_type::npos);
ss << '\'' << field_definition << '\'';
} else
ss << field_definition;
ss << " AS " << field_name;
}
m_field_definitions[field_number] = ss.str();
}
/**
Add FROM clause for the SELECT.
This function can be called more than once. The clause will be appended to
the previous FROM clause string.
@param from String representing the FROM clause.
*/
virtual void add_from(const String_type &from) {
m_from_clauses.push_back(from);
}
/**
Add WHERE clause for the SELECT.
This function can be called more than once. The clause will be appended to
the previous WHERE clause string.
@param where String representing the WHERE clause.
*/
virtual void add_where(const String_type &where) {
m_where_clauses.push_back(where);
}
/**
Add CTE expression before SELECT.
@param cte String representing the CTE expression.
*/
virtual void add_cte_expression(const String_type &cte) {
m_cte_expression = cte;
}
/**
Indicates that we should add DISTINCT clause to SELECT.
*/
virtual void add_distinct() { m_is_distinct = true; }
/**
Indicates selection of all field (SELECT '*').
*/
virtual void add_star() { m_add_star = true; }
/**
Get the field ordinal position number for the given field name.
@param field_name Column name for which the field number is returned.
@return Integer representing position of column in projection list.
*/
virtual int field_number(const String_type &field_name) const {
assert(m_field_numbers.find(field_name) != m_field_numbers.end());
return m_field_numbers.find(field_name)->second;
}
/**
Build the SELECT query that is used in the CREATE VIEW command.
@return The SELECT query string.
*/
String_type build_select_query() const {
Stringstream_type ss;
if (!m_cte_expression.empty()) ss << m_cte_expression << "\n ";
// Make SELECT [DISTINCT]
ss << "SELECT " << (m_is_distinct ? "DISTINCT \n" : "\n");
if (!m_add_star) {
// Output view column definitions
for (Field_definitions::const_iterator field =
m_field_definitions.begin();
field != m_field_definitions.end(); ++field) {
if (field != m_field_definitions.begin()) ss << ",\n";
ss << " " << field->second;
}
} else
ss << "*";
// Output FROM clauses
for (From_clauses::const_iterator from = m_from_clauses.begin();
from != m_from_clauses.end(); ++from) {
if (from == m_from_clauses.begin()) ss << " FROM ";
ss << "\n " << *from;
}
// Output WHERE clauses
for (Where_clauses::const_iterator where = m_where_clauses.begin();
where != m_where_clauses.end(); ++where) {
if (where == m_where_clauses.begin()) ss << " WHERE ";
ss << "\n " << *where;
}
ss << "\n";
return ss.str();
}
String_type build_ddl_create_view() const override {
Stringstream_type ss;
ss << "CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW "
<< "information_schema." << view_name() << " AS " + build_select_query();
return ss.str();
}
private:
// Map of field_names and the ordinal position in SELECT projection.
typedef std::map<String_type, int> Field_numbers;
// Map of field ordinal position and their view column definition.
typedef std::map<int, String_type> Field_definitions;
// List of FROM clause definition in the SELECT
typedef std::vector<String_type> From_clauses;
// List of WHERE clause definition in the SELECT
typedef std::vector<String_type> Where_clauses;
Field_numbers m_field_numbers;
Field_definitions m_field_definitions;
From_clauses m_from_clauses;
Where_clauses m_where_clauses;
dd::String_type m_cte_expression;
bool m_is_distinct{false};
bool m_add_star{false};
};
// This class is unused and kept here for future use.
class System_view_union_definition_impl : public System_view_definition_impl {
public:
/**
Get the object for a SELECT definition to be used in the UNION.
@return The System_view_select_definition_impl&.
*/
System_view_select_definition_impl &get_query_block() {
m_selects.push_back(
Select_definition(new System_view_select_definition_impl));
return *(m_selects.back().get());
}
String_type build_ddl_create_view() const override {
Stringstream_type ss;
bool first_query_block = true;
// Union definition must have minimum two SELECTs.
assert(m_selects.size() >= 2);
for (auto &select : m_selects) {
if (first_query_block) {
ss << "CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW "
<< "information_schema." << view_name() << " AS "
<< "(" << select->build_select_query() << ")";
first_query_block = false;
} else {
ss << " UNION "
<< "(" << select->build_select_query() << ")";
}
}
return ss.str();
}
private:
using Select_definition = std::unique_ptr<System_view_select_definition_impl>;
// Member holds SELECT's used for the UNION
std::vector<Select_definition> m_selects;
};
} // namespace system_views
} // namespace dd
#endif // DD_SYSTEM_VIEWS__SYSTEM_VIEW_DEFINITION_IMPL_INCLUDED