summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--table_sizes.cc418
2 files changed, 211 insertions, 210 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7392af9..e195e8d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,3 @@
1INCLUDE_DIRECTORIES(SYSTEM ${BOOST_PATCHES_DIR} ${BOOST_INCLUDE_DIR})
2
3MYSQL_ADD_PLUGIN(table_sizes 1MYSQL_ADD_PLUGIN(table_sizes
4 table_sizes.cc 2 table_sizes.cc
5 MODULE_ONLY MODULE_OUTPUT_NAME "table_sizes" 3 MODULE_ONLY MODULE_OUTPUT_NAME "table_sizes"
@@ -7,3 +5,4 @@ MYSQL_ADD_PLUGIN(table_sizes
7 ) 5 )
8 6
9ADD_DEFINITIONS(-DMYSQL_SERVER) 7ADD_DEFINITIONS(-DMYSQL_SERVER)
8ADD_DEFINITIONS(-DLOG_COMPONENT_TAG="TABLE_SIZES")
diff --git a/table_sizes.cc b/table_sizes.cc
index ec8efc0..ef12d19 100644
--- a/table_sizes.cc
+++ b/table_sizes.cc
@@ -13,8 +13,9 @@
13 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 13 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14*/ 14*/
15 15
16#include <mysql/plugin.h> 16#include "mysql/components/my_service.h"
17#include <boost/optional/optional.hpp> 17#include "mysql/components/services/log_builtins.h"
18#include "mysql/plugin.h"
18 19
19#include "sql/mysqld.h" 20#include "sql/mysqld.h"
20#include "sql/sql_base.h" 21#include "sql/sql_base.h"
@@ -30,10 +31,19 @@
30#include "sql/dd/string_type.h" // dd::String_type 31#include "sql/dd/string_type.h" // dd::String_type
31#include "sql/dd/sdi_file.h" // dd::sdi_file 32#include "sql/dd/sdi_file.h" // dd::sdi_file
32#include "sql/auth/auth_acls.h" // *_ACLS 33#include "sql/auth/auth_acls.h" // *_ACLS
33#include "sql/auth/auth_common.h" // check_grant_db 34#include "sql/auth/auth_common.h" // check_access + check_grant_db
34#include "mf_wcomp.h" // wild_compare,wild_one,wild_many 35#include "mf_wcomp.h" // wild_compare,wild_one,wild_many
35#include "my_dir.h" // MY_DIR 36#include "my_dir.h" // MY_DIR
36 37
38// MySQL 8.0 logger service interface
39static SERVICE_TYPE(registry) *reg_srv = nullptr;
40SERVICE_TYPE(log_builtins) *log_bi = nullptr;
41SERVICE_TYPE(log_builtins_string) *log_bs = nullptr;
42
43namespace table_sizes {
44
45static const char *IS_TABLE_NAME = "TABLE_SIZES";
46
37// InnoDB FTS 47// InnoDB FTS
38/** For storing table info when checking for orphaned tables. */ 48/** For storing table info when checking for orphaned tables. */
39struct fts_aux_table_t 49struct fts_aux_table_t
@@ -60,23 +70,23 @@ bool fts_is_aux_table_name(fts_aux_table_t *table, const char *name,
60 /** FTS auxiliary table suffixes that are common to all FT indexes. */ 70 /** FTS auxiliary table suffixes that are common to all FT indexes. */
61 const char *fts_common_tables[] = {"being_deleted", "being_deleted_cache", 71 const char *fts_common_tables[] = {"being_deleted", "being_deleted_cache",
62 "config", "deleted", 72 "config", "deleted",
63 "deleted_cache", NULL}; 73 "deleted_cache", nullptr};
64 const char *fts_common_tables_5_7[] = {"BEING_DELETED", "BEING_DELETED_CACHE", 74 const char *fts_common_tables_5_7[] = {"BEING_DELETED", "BEING_DELETED_CACHE",
65 "CONFIG", "DELETED", 75 "CONFIG", "DELETED",
66 "DELETED_CACHE", NULL}; 76 "DELETED_CACHE", nullptr};
67 77
68 /** FTS auxiliary INDEX split intervals. */ 78 /** FTS auxiliary INDEX split intervals. */
69 const char *fts_index_selector[] = {"index_1", "index_2", "index_3", "index_4", 79 const char *fts_index_selector[] = {"index_1", "index_2", "index_3", "index_4",
70 "index_5", "index_6", NULL}; 80 "index_5", "index_6", nullptr};
71 const char *fts_index_selector_5_7[] = {"INDEX_1", "INDEX_2", "INDEX_3", "INDEX_4", 81 const char *fts_index_selector_5_7[] = {"INDEX_1", "INDEX_2", "INDEX_3", "INDEX_4",
72 "INDEX_5", "INDEX_6", NULL}; 82 "INDEX_5", "INDEX_6", nullptr};
73 83
74 const char *ptr = name; 84 const char *ptr = name;
75 const char *end = name + len; 85 const char *end = name + len;
76 86
77 /* All auxiliary tables are prefixed with "FTS_" and the name 87 /* All auxiliary tables are prefixed with "FTS_" and the name
78 length will be at the very least greater than 20 bytes. */ 88 length will be at the very least greater than 20 bytes. */
79 if (ptr != NULL && len > 20 && 89 if (ptr != nullptr && len > 20 &&
80 (strncmp(ptr, FTS_PREFIX, 4) == 0 || 90 (strncmp(ptr, FTS_PREFIX, 4) == 0 ||
81 strncmp(ptr, FTS_PREFIX_5_7, 4) == 0)) 91 strncmp(ptr, FTS_PREFIX_5_7, 4) == 0))
82 { 92 {
@@ -90,15 +100,19 @@ bool fts_is_aux_table_name(fts_aux_table_t *table, const char *name,
90 100
91 /* Skip the table id. */ 101 /* Skip the table id. */
92 ptr = static_cast<const char *>(memchr(ptr, '_', len)); 102 ptr = static_cast<const char *>(memchr(ptr, '_', len));
93 if (ptr == NULL) 103 if (ptr == nullptr)
94 return false; 104 return false;
95 105
96 /* Skip the underscore. */ 106 /* Skip the underscore. */
97 ++ptr; 107 ++ptr;
98 len = end - ptr; 108 len = end - ptr;
99 109
110 /* It's not enough to be a FTS auxiliary table name */
111 if (len == 0)
112 return false;
113
100 /* First search the common table suffix array. */ 114 /* First search the common table suffix array. */
101 for (int i = 0; fts_common_tables[i] != NULL; ++i) { 115 for (int i = 0; fts_common_tables[i] != nullptr; ++i) {
102 if (strncmp(ptr, fts_common_tables[i], len) == 0 || 116 if (strncmp(ptr, fts_common_tables[i], len) == 0 ||
103 strncmp(ptr, fts_common_tables_5_7[i], len) == 0) { 117 strncmp(ptr, fts_common_tables_5_7[i], len) == 0) {
104 return true; 118 return true;
@@ -118,15 +132,19 @@ bool fts_is_aux_table_name(fts_aux_table_t *table, const char *name,
118 /* Skip the index id. */ 132 /* Skip the index id. */
119 ptr = static_cast<const char *>(memchr(ptr, '_', len)); 133 ptr = static_cast<const char *>(memchr(ptr, '_', len));
120 134
121 if (ptr == NULL) 135 if (ptr == nullptr)
122 return false; 136 return false;
123 137
124 /* Skip the underscore. */ 138 /* Skip the underscore. */
125 ++ptr; 139 ++ptr;
126 len = end - ptr; 140 len = end - ptr;
127 141
142 /* It's not enough to be a FTS auxiliary table name */
143 if (len == 0)
144 return false;
145
128 /* Search the FT index specific array. */ 146 /* Search the FT index specific array. */
129 for (int i = 0; fts_index_selector[i] != NULL; ++i) { 147 for (int i = 0; fts_index_selector[i] != nullptr; ++i) {
130 if (strncmp(ptr, fts_index_selector[i], len) == 0 || 148 if (strncmp(ptr, fts_index_selector[i], len) == 0 ||
131 strncmp(ptr, fts_index_selector_5_7[i], len) == 0) { 149 strncmp(ptr, fts_index_selector_5_7[i], len) == 0) {
132 return true; 150 return true;
@@ -143,58 +161,27 @@ bool fts_is_aux_table_name(fts_aux_table_t *table, const char *name,
143 161
144/*----------------------------------------------------------------------------*/ 162/*----------------------------------------------------------------------------*/
145 163
146/**
147 Condition pushdown used for INFORMATION_SCHEMA / SHOW queries.
148 This structure is to implement an optimization when
149 accessing data dictionary data in the INFORMATION_SCHEMA
150 or SHOW commands.
151 When the query contain a TABLE_SCHEMA or TABLE_NAME clause,
152 narrow the search for data based on the constraints given.
153*/
154struct LOOKUP_FIELD_VALUES { 164struct LOOKUP_FIELD_VALUES {
155 /** 165 std::map<dd::String_type, bool> db_values;
156 Value of a TABLE_SCHEMA clause. 166 std::map<dd::String_type, bool> table_values;
157 Note that this value length may exceed @c NAME_LEN.
158 */
159 boost::optional<dd::String_type> db_value;
160 /**
161 Value of a TABLE_NAME clause.
162 Note that this value length may exceed @c NAME_LEN.
163 */
164 boost::optional<dd::String_type> table_value;
165}; 167};
166 168
167/** 169static bool get_lookup_value(THD *thd, Item_func *item_func, Table_ref *table,
168 @brief Get lookup value from the part of 'WHERE' condition
169
170 @details This function gets lookup value from
171 the part of 'WHERE' condition if it's possible and
172 fill appropriate lookup_field_vals struct field
173 with this value.
174
175 @param[in] thd thread handler
176 @param[in] item_func part of WHERE condition
177 @param[in] table I_S table
178 @param[in, out] lookup_field_vals Struct which holds lookup values
179
180 @return
181 0 success
182 1 error, there can be no matching records for the condition
183*/
184
185static bool get_lookup_value(Item_func *item_func, Table_ref *table,
186 LOOKUP_FIELD_VALUES *lookup_field_vals) 170 LOOKUP_FIELD_VALUES *lookup_field_vals)
187{ 171{
188 ST_SCHEMA_TABLE *schema_table = table->schema_table; 172 ST_SCHEMA_TABLE *schema_table = table->schema_table;
189 ST_FIELD_INFO *field_info = schema_table->fields_info; 173 ST_FIELD_INFO *field_info = schema_table->fields_info;
190 174
175 String foo;
176 item_func->print(thd, &foo, QT_ORDINARY);
177
191 if (item_func->functype() == Item_func::EQ_FUNC || 178 if (item_func->functype() == Item_func::EQ_FUNC ||
192 item_func->functype() == Item_func::EQUAL_FUNC) { 179 item_func->functype() == Item_func::EQUAL_FUNC ||
180 item_func->functype() == Item_func::LIKE_FUNC) {
193 int idx_field, idx_val; 181 int idx_field, idx_val;
194 char tmp[MAX_FIELD_WIDTH]; 182 char tmp[MAX_FIELD_WIDTH];
195 String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info); 183 String *tmp_str, str_buf(tmp, sizeof(tmp), system_charset_info);
196 Item_field *item_field; 184 bool is_wildcard = (item_func->functype() == Item_func::LIKE_FUNC);
197 CHARSET_INFO *cs = system_charset_info;
198 185
199 if (item_func->arguments()[0]->type() == Item::FIELD_ITEM && 186 if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
200 item_func->arguments()[1]->const_item()) { 187 item_func->arguments()[1]->const_item()) {
@@ -207,109 +194,93 @@ static bool get_lookup_value(Item_func *item_func, Table_ref *table,
207 } else 194 } else
208 return 0; 195 return 0;
209 196
210 item_field = (Item_field *)item_func->arguments()[idx_field]; 197 Item_field *item_field = (Item_field *)item_func->arguments()[idx_field];
211 if (table->table != item_field->field->table) return 0; 198 if (table->table != item_field->field->table)
212 tmp_str = item_func->arguments()[idx_val]->val_str(&str_buff); 199 return 0;
213 200
214 /* impossible value */ 201 tmp_str = item_func->arguments()[idx_val]->val_str(&str_buf);
215 if (!tmp_str) return 1; 202 if (!tmp_str || !tmp_str->length())
203 return 0;
204 if (lower_case_table_names && files_charset_info->casedn_multiply == 1)
205 my_casedn_str(files_charset_info, tmp_str->c_ptr_quick());
216 206
217 /* Lookup value is database name */ 207 if (my_strcasecmp(system_charset_info, item_field->field_name,
218 if (!cs->coll->strnncollsp(cs, (const uchar *)field_info[0].field_name, 208 field_info[0].field_name) == 0) {
219 strlen(field_info[0].field_name), 209 /* Lookup value is database name */
220 (const uchar *)item_field->field_name, 210 lookup_field_vals->db_values[dd::String_type(tmp_str->ptr(), tmp_str->length())] = is_wildcard;
221 strlen(item_field->field_name))) {
222 lookup_field_vals->db_value.emplace(tmp_str->ptr(), tmp_str->length());
223 } 211 }
224 /* Lookup value is table name */ 212 else if (my_strcasecmp(system_charset_info, item_field->field_name,
225 else if (!cs->coll->strnncollsp(cs, (const uchar *)field_info[1].field_name, 213 field_info[1].field_name) == 0) {
226 strlen(field_info[1].field_name), 214 /* Lookup value is table name */
227 (const uchar *)item_field->field_name, 215 lookup_field_vals->table_values[dd::String_type(tmp_str->ptr(), tmp_str->length())] = is_wildcard;
228 strlen(item_field->field_name))) {
229 lookup_field_vals->table_value.emplace(tmp_str->ptr(), tmp_str->length());
230 } 216 }
231 } 217 }
232 return 0; 218 else if (item_func->functype() == Item_func::IN_FUNC)
233} 219 {
220 Item_func_in *in_func = static_cast<Item_func_in *>(item_func);
221 char tmp[MAX_FIELD_WIDTH];
222 String *tmp_str, str_buf(tmp, sizeof(tmp), system_charset_info);
223
224 if (in_func->arguments()[0]->type() != Item::FIELD_ITEM)
225 return 0;
226
227 Item_field *item_field = (Item_field *)in_func->arguments()[0];
228 if (table->table != item_field->field->table)
229 return 0;
234 230
235/** 231 for (uint i = 1; i < in_func->arg_count; ++i)
236 @brief Calculates lookup values from 'WHERE' condition 232 {
233 if (in_func->arguments()[i] == nullptr)
234 continue;
237 235
238 @details This function calculates lookup value(database name, table name) 236 tmp_str = in_func->arguments()[i]->val_str(&str_buf);
239 from 'WHERE' condition if it's possible and 237 if (!tmp_str || !tmp_str->length())
240 fill lookup_field_vals struct fields with these values. 238 continue;
239 if (lower_case_table_names && files_charset_info->casedn_multiply == 1)
240 my_casedn_str(files_charset_info, tmp_str->c_ptr_quick());
241 241
242 @param[in] thd thread handler 242 /* Lookup value is database name */
243 @param[in] cond WHERE condition 243 if (my_strcasecmp(system_charset_info, item_field->field_name,
244 @param[in] table I_S table 244 field_info[0].field_name) == 0) {
245 @param[in, out] lookup_field_vals Struct which holds lookup values 245 lookup_field_vals->db_values[dd::String_type(tmp_str->ptr(), tmp_str->length())] = false;
246 }
247 else if (my_strcasecmp(system_charset_info, item_field->field_name,
248 field_info[1].field_name) == 0) {
249 lookup_field_vals->table_values[dd::String_type(tmp_str->ptr(), tmp_str->length())] = false;
250 }
251 }
252 }
246 253
247 @return 254 return 0;
248 0 success 255}
249 1 error, there can be no matching records for the condition
250*/
251 256
252static bool calc_lookup_values_from_cond(Item *cond, 257static bool calc_lookup_values_from_cond(THD *thd, Item *cond,
253 Table_ref *table, LOOKUP_FIELD_VALUES *lookup_field_vals) 258 Table_ref *table, LOOKUP_FIELD_VALUES *lookup_field_vals)
254{ 259{
255 if (!cond) return 0; 260 if (!cond) return 0;
256 261
257 if (cond->type() == Item::COND_ITEM) { 262 if (cond->type() == Item::COND_ITEM) {
258 if (((Item_cond *)cond)->functype() == Item_func::COND_AND_FUNC) { 263 auto func_type = ((Item_cond *)cond)->functype();
264 if (func_type == Item_func::COND_AND_FUNC) {
259 List_iterator<Item> li(*((Item_cond *)cond)->argument_list()); 265 List_iterator<Item> li(*((Item_cond *)cond)->argument_list());
260 Item *item; 266 Item *item;
261 while ((item = li++)) { 267 while ((item = li++)) {
262 if (item->type() == Item::FUNC_ITEM) { 268 if (item->type() == Item::FUNC_ITEM) {
263 if (get_lookup_value((Item_func *)item, table, lookup_field_vals)) 269 if (get_lookup_value(thd, (Item_func *)item, table, lookup_field_vals))
264 return 1; 270 return 1;
265 } else { 271 } else {
266 if (calc_lookup_values_from_cond(item, table, lookup_field_vals)) 272 if (calc_lookup_values_from_cond(thd, item, table, lookup_field_vals))
267 return 1; 273 return 1;
268 } 274 }
269 } 275 }
270 } 276 }
271 return 0; 277 return 0;
272 } else if (cond->type() == Item::FUNC_ITEM && 278 } else if (cond->type() == Item::FUNC_ITEM &&
273 get_lookup_value((Item_func *)cond, table, lookup_field_vals)) 279 get_lookup_value(thd, (Item_func *)cond, table, lookup_field_vals))
274 return 1; 280 return 1;
275 return 0; 281 return 0;
276} 282}
277 283
278/**
279 @brief Calculate lookup values(database name, table name)
280
281 @details This function calculates lookup values(database name, table name)
282 from 'WHERE' condition and fill lookup_field_vals struct field
283 with these values.
284
285 @param[in] cond WHERE condition
286 @param[in] tables I_S table
287 @param[in, out] lookup_field_vals Struct which holds lookup values
288
289 @return
290 0 success
291 1 error, there can be no matching records for the condition
292*/
293
294static bool get_lookup_field_values(Item *cond, Table_ref *tables,
295 LOOKUP_FIELD_VALUES *lookup_field_vals)
296{
297 bool rc = calc_lookup_values_from_cond(cond, tables, lookup_field_vals);
298
299 if (lower_case_table_names && !rc) {
300 /*
301 We can safely do in-place upgrades here since all of the above cases
302 are allocating a new memory buffer for these strings.
303 */
304 if (lookup_field_vals->db_value && !lookup_field_vals->db_value->empty())
305 casedn(system_charset_info, *lookup_field_vals->db_value);
306 if (lookup_field_vals->table_value && !lookup_field_vals->table_value->empty())
307 casedn(system_charset_info, *lookup_field_vals->table_value);
308 }
309
310 return rc;
311}
312
313/*----------------------------------------------------------------------------*/ 284/*----------------------------------------------------------------------------*/
314 285
315static bool is_special_db(const dd::String_type &db_name) 286static bool is_special_db(const dd::String_type &db_name)
@@ -319,33 +290,9 @@ static bool is_special_db(const dd::String_type &db_name)
319 || is_perfschema_db(db_name.c_str(), db_name.size()); 290 || is_perfschema_db(db_name.c_str(), db_name.size());
320} 291}
321 292
322/**
323 Return either single or all schemas
324
325 @param[in] thd thread handler
326 @param[out] db_names list of schemas
327 @param[in] lookup_field_vals Struct which holds lookup values
328
329 @return true if error, false otherwise
330*/
331static int make_db_list(THD *thd, std::vector<dd::String_type> *db_names, 293static int make_db_list(THD *thd, std::vector<dd::String_type> *db_names,
332 LOOKUP_FIELD_VALUES *lookup_field_vals) 294 LOOKUP_FIELD_VALUES *lookup_field_vals)
333{ 295{
334 /*
335 If we have db lookup value we just add it to list and
336 exit from the function.
337 We don't do this for database names longer than the maximum
338 path length.
339 */
340 if (lookup_field_vals->db_value
341 && lookup_field_vals->db_value->length() <= NAME_LEN)
342 {
343 const dd::String_type &db_name = lookup_field_vals->db_value.get();
344 if (!is_special_db(db_name))
345 db_names->push_back(db_name);
346 return 0;
347 }
348
349 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client()); 296 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
350 std::vector<const dd::Schema *> schemas; 297 std::vector<const dd::Schema *> schemas;
351 if (thd->dd_client()->fetch_global_components(&schemas)) 298 if (thd->dd_client()->fetch_global_components(&schemas))
@@ -354,28 +301,34 @@ static int make_db_list(THD *thd, std::vector<dd::String_type> *db_names,
354 for (const dd::Schema *schema_obj : schemas) 301 for (const dd::Schema *schema_obj : schemas)
355 { 302 {
356 const dd::String_type &db_name = schema_obj->name(); 303 const dd::String_type &db_name = schema_obj->name();
357 if (is_special_db(db_name)) 304 if (db_name.length() > NAME_LEN || is_special_db(db_name))
358 continue; 305 continue;
359 db_names->push_back(db_name); 306 bool match = true;
307 for (auto &db_value : lookup_field_vals->db_values)
308 {
309 dd::String_type wildx = db_value.first;
310 match = (db_value.second)
311 ? (lower_case_table_names)
312 ? !my_wildcmp(files_charset_info,
313 db_name.c_str(), db_name.c_str() + db_name.length(),
314 wildx.c_str(), wildx.c_str() + wildx.length(),
315 wild_prefix, wild_one, wild_many)
316 : !wild_compare(db_name.c_str(), db_name.length(), wildx.c_str(), wildx.length(), 0)
317 : (my_strcasecmp(files_charset_info, db_name.c_str(), wildx.c_str()) == 0);
318 if (match)
319 break;
320 }
321 if (match)
322 db_names->push_back(db_name);
360 } 323 }
361 return 0; 324 return 0;
362} 325}
363 326
364/*----------------------------------------------------------------------------*/ 327/*----------------------------------------------------------------------------*/
365 328
366/**
367 Find files in a given directory.
368
369 @param thd thread handler
370 @param tables put found files in this list
371 @param db_name filter for found files
372 @param wild filter for found files
373
374 @return true if error, false otherwise
375*/
376typedef std::map<dd::String_type, size_t> Table_sizes_map; 329typedef std::map<dd::String_type, size_t> Table_sizes_map;
377bool find_tables(THD *thd, Table_sizes_map &tables, 330static bool find_tables(THD *thd, Table_sizes_map &tables,
378 Table_ref &db_data, boost::optional<dd::String_type> &wild) 331 Table_ref &db_data, std::map<dd::String_type, bool> &wild)
379{ 332{
380 MY_DIR *dirp; 333 MY_DIR *dirp;
381 DBUG_ENTER("find_files"); 334 DBUG_ENTER("find_files");
@@ -396,6 +349,10 @@ bool find_tables(THD *thd, Table_sizes_map &tables,
396 return true; 349 return true;
397 } 350 }
398 351
352 /* check global privilege */
353 bool has_global_show = (thd->security_context()
354 ->master_access(db_data.db) & (DB_OP_ACLS | SHOW_DB_ACL));
355
399 char uname[NAME_LEN + 1]; /* Unencoded name */ 356 char uname[NAME_LEN + 1]; /* Unencoded name */
400 dd::String_type fts_schema_name, fts_table_name; /* FTS lookup */ 357 dd::String_type fts_schema_name, fts_table_name; /* FTS lookup */
401 std::map<dd::Object_id, dd::String_type> fts_cache; 358 std::map<dd::Object_id, dd::String_type> fts_cache;
@@ -444,19 +401,23 @@ bool find_tables(THD *thd, Table_sizes_map &tables,
444 continue; 401 continue;
445 } 402 }
446 403
447 if (wild) 404 bool match = true;
405 for (auto &wild_entry : wild)
448 { 406 {
449 if (lower_case_table_names) 407 dd::String_type wildx = wild_entry.first;
450 { 408 match = (wild_entry.second)
451 if (my_wildcmp(files_charset_info, 409 ? (lower_case_table_names)
452 uname, uname + file_name_len, 410 ? !my_wildcmp(files_charset_info,
453 wild->c_str(), wild->c_str() + wild->length(), 411 uname, uname + file_name_len,
454 wild_prefix, wild_one, wild_many)) 412 wildx.c_str(), wildx.c_str() + wildx.length(),
455 continue; 413 wild_prefix, wild_one, wild_many)
456 } 414 : !wild_compare(uname, file_name_len, wildx.c_str(), wildx.length(), 0)
457 else if (wild_compare(uname, file_name_len, wild->c_str(), wild->length(), 0)) 415 : (my_strcasecmp(files_charset_info, uname, wildx.c_str()) == 0);
458 continue; 416 if (match)
417 break;
459 } 418 }
419 if (!match)
420 continue;
460 421
461 /* 422 /*
462 Check_grant will grant access if there is any column privileges on 423 Check_grant will grant access if there is any column privileges on
@@ -464,7 +425,7 @@ bool find_tables(THD *thd, Table_sizes_map &tables,
464 */ 425 */
465 db_data.table_name = uname; 426 db_data.table_name = uname;
466 db_data.table_name_length = file_name_len; 427 db_data.table_name_length = file_name_len;
467 if (check_grant(thd, SELECT_ACL, &db_data, true, 1, true)) 428 if (!has_global_show && check_grant(thd, SELECT_ACL, &db_data, true, 1, true))
468 continue; 429 continue;
469 430
470 tables.emplace(uname, file->mystat->st_size); 431 tables.emplace(uname, file->mystat->st_size);
@@ -479,11 +440,11 @@ bool find_tables(THD *thd, Table_sizes_map &tables,
479static bool make_table_list(THD *thd, Table_sizes_map &table_names, 440static bool make_table_list(THD *thd, Table_sizes_map &table_names,
480 LOOKUP_FIELD_VALUES *lookup_field_vals, Table_ref &db_data) 441 LOOKUP_FIELD_VALUES *lookup_field_vals, Table_ref &db_data)
481{ 442{
482 const dd::Schema *sch_obj = NULL; 443 const dd::Schema *sch_obj = nullptr;
483 if (thd->dd_client()->acquire(db_data.db, &sch_obj) || !sch_obj) 444 if (thd->dd_client()->acquire(db_data.db, &sch_obj) || !sch_obj)
484 return 1; 445 return 1;
485 446
486 return find_tables(thd, table_names, db_data, lookup_field_vals->table_value); 447 return find_tables(thd, table_names, db_data, lookup_field_vals->table_values);
487} 448}
488 449
489/*----------------------------------------------------------------------------*/ 450/*----------------------------------------------------------------------------*/
@@ -497,22 +458,39 @@ static ST_FIELD_INFO fields_info[] =
497 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} 458 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
498}; 459};
499 460
461static bool can_access_database(THD *thd, Table_ref &db_data)
462{
463 Security_context *sctx = thd->security_context();
464
465 /* check global privileges */
466 if (sctx->master_access(db_data.db) & (DB_OP_ACLS | SHOW_DB_ACL))
467 return true;
468
469 /* check db privileges */
470 Access_bitmask db_access = sctx->check_db_level_access(thd, db_data.db, db_data.db_length);
471 //if (check_access(thd, SELECT_ACL, db_data.db, &db_access, nullptr, false, true))
472 // return false;
473 if (db_access) {
474 db_data.grant.privilege = db_access;
475 return true;
476 }
477
478 /* check specific table privileges */
479 if (!check_grant_db(thd, db_data.db))
480 return true;
481
482 return false;
483}
484
500static int fill_table(THD *thd, Table_ref *tables, Item *cond) 485static int fill_table(THD *thd, Table_ref *tables, Item *cond)
501{ 486{
502 TABLE *table = tables->table; 487 TABLE *table = tables->table;
503 LOOKUP_FIELD_VALUES lookup_field_vals; 488 LOOKUP_FIELD_VALUES lookup_field_vals = {};
504 std::vector<dd::String_type> db_names; 489 std::vector<dd::String_type> db_names;
505 490
506 DBUG_ENTER("fill_table"); 491 if (calc_lookup_values_from_cond(thd, cond, tables, &lookup_field_vals))
507
508 if (get_lookup_field_values(cond, tables, &lookup_field_vals))
509 return 0; 492 return 0;
510 493
511#define STR_OR_NIL(S) ((S) ? (S->c_str()) : "<nil>")
512 DBUG_PRINT("INDEX VALUES", ("db_name='%s', table_name='%s'",
513 STR_OR_NIL(lookup_field_vals.db_value),
514 STR_OR_NIL(lookup_field_vals.table_value)));
515
516 /* EXPLAIN SELECT */ 494 /* EXPLAIN SELECT */
517 if (thd->lex->is_explain()) 495 if (thd->lex->is_explain())
518 return 0; 496 return 0;
@@ -528,13 +506,7 @@ static int fill_table(THD *thd, Table_ref *tables, Item *cond)
528 db_data.db_length = db_name.length(); 506 db_data.db_length = db_name.length();
529 db_data.grant.privilege = 0; 507 db_data.grant.privilege = 0;
530 508
531 // Get user's global and db-level privileges. 509 if (!can_access_database(thd, db_data))
532 if (check_access(thd, SELECT_ACL, db_data.db, &db_data.grant.privilege, NULL, false, true))
533 continue;
534
535 // Now check, if user has access on global level or to any of database/
536 // table/column/routine.
537 if (!(db_data.grant.privilege & DB_OP_ACLS) && check_grant_db(thd, db_data.db))
538 continue; 510 continue;
539 511
540 // We must make sure the schema is released and unlocked in the right 512 // We must make sure the schema is released and unlocked in the right
@@ -565,33 +537,63 @@ static int fill_table(THD *thd, Table_ref *tables, Item *cond)
565 return 0; 537 return 0;
566} 538}
567 539
568static int init(void *ptr) 540static int view_init(void *ptr)
569{ 541{
542 if (init_logging_service_for_plugin(&reg_srv, &log_bi, &log_bs))
543 return 1;
544
545 LogErr(INFORMATION_LEVEL, ER_LOG_PRINTF_MSG,
546 "Plugin table_sizes initializing...");
547
548 if (reg_srv == nullptr)
549 {
550 LogPluginErrMsg(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "reg_srv is NULL in init");
551 return 1;
552 }
553
570 ST_SCHEMA_TABLE *schema_table = (ST_SCHEMA_TABLE*)ptr; 554 ST_SCHEMA_TABLE *schema_table = (ST_SCHEMA_TABLE*)ptr;
571 555
572 schema_table->fields_info = fields_info; 556 schema_table->table_name = IS_TABLE_NAME;
573 schema_table->fill_table = fill_table; 557 schema_table->fields_info = fields_info;
558 schema_table->fill_table = fill_table;
559 schema_table->old_format = nullptr;
560 schema_table->process_table = nullptr;
561 return 0;
562}
563
564static int view_deinit(void *)
565{
566 LogPluginErrMsg(INFORMATION_LEVEL, ER_LOG_PRINTF_MSG,
567 "Plugin table_sizes de-initializing...");
568
569 if (reg_srv == nullptr)
570 LogPluginErrMsg(ERROR_LEVEL, ER_LOG_PRINTF_MSG, "reg_srv is NULL in deinit");
571 else
572 deinit_logging_service_for_plugin(&reg_srv, &log_bi, &log_bs);
573
574 return 0; 574 return 0;
575} 575}
576 576
577static struct st_mysql_information_schema info = 577static struct st_mysql_information_schema info =
578{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; 578{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
579 579
580} // namespace table_sizes
581
580mysql_declare_plugin(table_sizes) 582mysql_declare_plugin(table_sizes)
581{ 583{
582 MYSQL_INFORMATION_SCHEMA_PLUGIN, 584 MYSQL_INFORMATION_SCHEMA_PLUGIN, /* type */
583 &info, /* type-specific descriptor */ 585 &table_sizes::info, /* descriptor */
584 "TABLE_SIZES", /* table name */ 586 table_sizes::IS_TABLE_NAME, /* name */
585 "Manuel Mausz", /* author */ 587 "Manuel Mausz", /* author */
586 "Fast INFORMATION_SCHEMA table sizes", /* description */ 588 "Fast INFORMATION_SCHEMA table sizes", /* description */
587 PLUGIN_LICENSE_GPL, /* license type */ 589 PLUGIN_LICENSE_GPL, /* plugin license */
588 init, /* init function */ 590 table_sizes::view_init, /* init function (when loaded) */
589 NULL, 591 nullptr, /* check uninstall function */
590 NULL, 592 table_sizes::view_deinit, /* deinit function (when unloaded) */
591 0x0800, /* version = 8.0 */ 593 0x0840, /* version = 8.4 */
592 NULL, /* no status variables */ 594 nullptr, /* status variables */
593 NULL, /* no system variables */ 595 nullptr, /* system variables */
594 NULL, /* no reserved information */ 596 nullptr, /* reserved information */
595 0 /* no flags */ 597 0 /* flags */
596} 598}
597mysql_declare_plugin_end; 599mysql_declare_plugin_end;