summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/table_sizes.cc724
2 files changed, 0 insertions, 732 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 7965ee4..0000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,8 +0,0 @@
1INCLUDES = $(MYSQL_INC) $(DEPS_CFLAGS)
2
3pkgplugindir = $(MYSQL_PLUGIN_DIR)
4
5pkgplugin_LTLIBRARIES = table_sizes.la
6table_sizes_la_SOURCES = table_sizes.cc
7table_sizes_la_LIBADD = $(DEPS_LIBS)
8table_sizes_la_LDFLAGS = -module
diff --git a/src/table_sizes.cc b/src/table_sizes.cc
deleted file mode 100644
index 40d5090..0000000
--- a/src/table_sizes.cc
+++ /dev/null
@@ -1,724 +0,0 @@
1/*
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; version 2 of the License.
5
6 This program is distributed in the hope that it will be useful,
7 but WITHOUT ANY WARRANTY; without even the implied warranty of
8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 GNU General Public License for more details.
10
11 You should have received a copy of the GNU General Public License
12 along with this program; if not, write to the Free Software
13 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14*/
15
16#include <mysql/plugin.h>
17#include <boost/optional/optional.hpp>
18
19#include "sql/mysqld.h"
20#include "sql/sql_base.h"
21#include "sql/sql_show.h"
22#include "sql/sql_class.h" // THD
23#include "sql/sql_table.h" // filename_to_tablename
24#include "sql/strfunc.h" // make_lex_string_root
25#include "sql/sql_parse.h" // sql_command_flags
26#include "sql/sql_lex.h" // LEX
27#include "sql/item_func.h" // Item_Func
28#include "sql/item_cmpfunc.h" // Item_cond
29#include "sql/dd/cache/dictionary_client.h" // dd::cache::Dictionary_client
30#include "sql/dd/dd_schema.h" // dd::Schema_MDL_locker
31#include "sql/dd/string_type.h" // dd::String_type
32#include "sql/dd/sdi_file.h" // dd::sdi_file
33#include "sql/auth/auth_acls.h" // *_ACLS
34#include "sql/auth/auth_common.h" // check_grant_db
35#include "mf_wcomp.h" // wild_compare,wild_one,wild_many
36#include "my_dir.h" // MY_DIR
37
38// InnoDB FTS
39/** For storing table info when checking for orphaned tables. */
40struct fts_aux_table_t
41{
42 /** Parent table id */
43 uint64_t parent_id;
44
45 /** Table FT index id */
46 uint64_t index_id;
47};
48
49/** Check if a table is an FTS auxiliary table name.
50@param[out] table FTS table info
51@param[in] name Table name
52@param[in] len Length of table name
53@return true if the name matches an auxiliary table name pattern */
54bool fts_is_aux_table_name(fts_aux_table_t *table, const char *name,
55 int len)
56{
57 /** FTS auxiliary table prefix that are common to all FT indexes.*/
58 const char *FTS_PREFIX = "fts_";
59 const char *FTS_PREFIX_5_7 = "FTS_";
60
61 /** FTS auxiliary table suffixes that are common to all FT indexes. */
62 const char *fts_common_tables[] = {"being_deleted", "being_deleted_cache",
63 "config", "deleted",
64 "deleted_cache", NULL};
65 const char *fts_common_tables_5_7[] = {"BEING_DELETED", "BEING_DELETED_CACHE",
66 "CONFIG", "DELETED",
67 "DELETED_CACHE", NULL};
68
69 /** FTS auxiliary INDEX split intervals. */
70 const char *fts_index_selector[] = {"index_1", "index_2", "index_3", "index_4",
71 "index_5", "index_6", NULL};
72 const char *fts_index_selector_5_7[] = {"INDEX_1", "INDEX_2", "INDEX_3", "INDEX_4",
73 "INDEX_5", "INDEX_6", NULL};
74
75 const char *ptr = name;
76 const char *end = name + len;
77
78 /* All auxiliary tables are prefixed with "FTS_" and the name
79 length will be at the very least greater than 20 bytes. */
80 if (ptr != NULL && len > 20 &&
81 (strncmp(ptr, FTS_PREFIX, 4) == 0 ||
82 strncmp(ptr, FTS_PREFIX_5_7, 4) == 0))
83 {
84 /* Skip the prefix. */
85 ptr += 4;
86 len -= 4;
87
88 /* Try and read the table id. */
89 if (sscanf(ptr, "%016" PRIx64, &table->parent_id) != 1)
90 return false;
91
92 /* Skip the table id. */
93 ptr = static_cast<const char *>(memchr(ptr, '_', len));
94 if (ptr == NULL)
95 return false;
96
97 /* Skip the underscore. */
98 ++ptr;
99 len = end - ptr;
100
101 /* First search the common table suffix array. */
102 for (int i = 0; fts_common_tables[i] != NULL; ++i) {
103 if (strncmp(ptr, fts_common_tables[i], len) == 0 ||
104 strncmp(ptr, fts_common_tables_5_7[i], len) == 0) {
105 return true;
106 }
107 }
108
109 /* Could be obsolete common tables. */
110 if (native_strncasecmp(ptr, "ADDED", len) == 0 ||
111 native_strncasecmp(ptr, "STOPWORDS", len) == 0) {
112 return true;
113 }
114
115 /* Try and read the index id. */
116 if (sscanf(ptr, "%016" PRIx64, &table->index_id) != 1)
117 return false;
118
119 /* Skip the index id. */
120 ptr = static_cast<const char *>(memchr(ptr, '_', len));
121
122 if (ptr == NULL)
123 return false;
124
125 /* Skip the underscore. */
126 ++ptr;
127 len = end - ptr;
128
129 /* Search the FT index specific array. */
130 for (int i = 0; fts_index_selector[i] != NULL; ++i) {
131 if (strncmp(ptr, fts_index_selector[i], len) == 0 ||
132 strncmp(ptr, fts_index_selector_5_7[i], len) == 0) {
133 return true;
134 }
135 }
136
137 /* Other FT index specific table(s). */
138 if (native_strncasecmp(ptr, "DOC_ID", len) == 0)
139 return true;
140 }
141
142 return false;
143}
144
145/*----------------------------------------------------------------------------*/
146
147/**
148 Condition pushdown used for INFORMATION_SCHEMA / SHOW queries.
149 This structure is to implement an optimization when
150 accessing data dictionary data in the INFORMATION_SCHEMA
151 or SHOW commands.
152 When the query contain a TABLE_SCHEMA or TABLE_NAME clause,
153 narrow the search for data based on the constraints given.
154*/
155struct LOOKUP_FIELD_VALUES {
156 /**
157 Value of a TABLE_SCHEMA clause.
158 Note that this value length may exceed @c NAME_LEN.
159 @sa wild_db_value
160 */
161 boost::optional<dd::String_type> db_value;
162 /**
163 Value of a TABLE_NAME clause.
164 Note that this value length may exceed @c NAME_LEN.
165 @sa wild_table_value
166 */
167 boost::optional<dd::String_type> table_value;
168 /**
169 True when @c db_value is a LIKE clause,
170 false when @c db_value is an '=' clause.
171 */
172 bool wild_db_value = {false};
173 /**
174 True when @c table_value is a LIKE clause,
175 false when @c table_value is an '=' clause.
176 */
177 bool wild_table_value = {false};
178};
179
180/**
181 @brief Get lookup value from the part of 'WHERE' condition
182
183 @details This function gets lookup value from
184 the part of 'WHERE' condition if it's possible and
185 fill appropriate lookup_field_vals struct field
186 with this value.
187
188 @param[in] thd thread handler
189 @param[in] item_func part of WHERE condition
190 @param[in] table I_S table
191 @param[in, out] lookup_field_vals Struct which holds lookup values
192
193 @return
194 0 success
195 1 error, there can be no matching records for the condition
196*/
197
198static bool get_lookup_value(Item_func *item_func, TABLE_LIST *table,
199 LOOKUP_FIELD_VALUES *lookup_field_vals)
200{
201 ST_SCHEMA_TABLE *schema_table = table->schema_table;
202 ST_FIELD_INFO *field_info = schema_table->fields_info;
203 const char *field_name1 =
204 schema_table->idx_field1 >= 0
205 ? field_info[schema_table->idx_field1].field_name
206 : "";
207 const char *field_name2 =
208 schema_table->idx_field2 >= 0
209 ? field_info[schema_table->idx_field2].field_name
210 : "";
211
212 if (item_func->functype() == Item_func::EQ_FUNC ||
213 item_func->functype() == Item_func::EQUAL_FUNC) {
214 int idx_field, idx_val;
215 char tmp[MAX_FIELD_WIDTH];
216 String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
217 Item_field *item_field;
218 CHARSET_INFO *cs = system_charset_info;
219
220 if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
221 item_func->arguments()[1]->const_item()) {
222 idx_field = 0;
223 idx_val = 1;
224 } else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
225 item_func->arguments()[0]->const_item()) {
226 idx_field = 1;
227 idx_val = 0;
228 } else
229 return 0;
230
231 item_field = (Item_field *)item_func->arguments()[idx_field];
232 if (table->table != item_field->field->table) return 0;
233 tmp_str = item_func->arguments()[idx_val]->val_str(&str_buff);
234
235 /* impossible value */
236 if (!tmp_str) return 1;
237
238 /* Lookup value is database name */
239 if (!cs->coll->strnncollsp(cs, (uchar *)field_name1, strlen(field_name1),
240 (uchar *)item_field->field_name,
241 strlen(item_field->field_name))) {
242 lookup_field_vals->db_value.emplace(tmp_str->ptr(), tmp_str->length());
243 }
244 /* Lookup value is table name */
245 else if (!cs->coll->strnncollsp(cs, (uchar *)field_name2,
246 strlen(field_name2),
247 (uchar *)item_field->field_name,
248 strlen(item_field->field_name))) {
249 lookup_field_vals->table_value.emplace(tmp_str->ptr(), tmp_str->length());
250 }
251 }
252 return 0;
253}
254
255/**
256 @brief Calculates lookup values from 'WHERE' condition
257
258 @details This function calculates lookup value(database name, table name)
259 from 'WHERE' condition if it's possible and
260 fill lookup_field_vals struct fields with these values.
261
262 @param[in] thd thread handler
263 @param[in] cond WHERE condition
264 @param[in] table I_S table
265 @param[in, out] lookup_field_vals Struct which holds lookup values
266
267 @return
268 0 success
269 1 error, there can be no matching records for the condition
270*/
271
272static bool calc_lookup_values_from_cond(Item *cond,
273 TABLE_LIST *table, LOOKUP_FIELD_VALUES *lookup_field_vals)
274{
275 if (!cond) return 0;
276
277 if (cond->type() == Item::COND_ITEM) {
278 if (((Item_cond *)cond)->functype() == Item_func::COND_AND_FUNC) {
279 List_iterator<Item> li(*((Item_cond *)cond)->argument_list());
280 Item *item;
281 while ((item = li++)) {
282 if (item->type() == Item::FUNC_ITEM) {
283 if (get_lookup_value((Item_func *)item, table, lookup_field_vals))
284 return 1;
285 } else {
286 if (calc_lookup_values_from_cond(item, table, lookup_field_vals))
287 return 1;
288 }
289 }
290 }
291 return 0;
292 } else if (cond->type() == Item::FUNC_ITEM &&
293 get_lookup_value((Item_func *)cond, table, lookup_field_vals))
294 return 1;
295 return 0;
296}
297
298/**
299 @brief Calculate lookup values(database name, table name)
300
301 @details This function calculates lookup values(database name, table name)
302 from 'WHERE' condition or wild values (for 'SHOW' commands only)
303 from LEX struct and fill lookup_field_vals struct field
304 with these values.
305
306 @param[in] thd thread handler
307 @param[in] cond WHERE condition
308 @param[in] tables I_S table
309 @param[in, out] lookup_field_values Struct which holds lookup values
310
311 @return
312 0 success
313 1 error, there can be no matching records for the condition
314*/
315
316static bool get_lookup_field_values(THD *thd, Item *cond, TABLE_LIST *tables,
317 LOOKUP_FIELD_VALUES *lookup_field_values)
318{
319 LEX *lex = thd->lex;
320 const char *wild = lex->wild ? lex->wild->ptr() : NullS;
321 bool rc = 0;
322
323 switch (lex->sql_command) {
324 case SQLCOM_SHOW_DATABASES:
325 if (wild) {
326 lookup_field_values->db_value = wild;
327 lookup_field_values->wild_db_value = true;
328 }
329 break;
330 case SQLCOM_SHOW_TABLES:
331 case SQLCOM_SHOW_TABLE_STATUS:
332 case SQLCOM_SHOW_TRIGGERS:
333 case SQLCOM_SHOW_EVENTS:
334 lookup_field_values->db_value = lex->select_lex->db;
335 if (wild) {
336 lookup_field_values->table_value = wild;
337 lookup_field_values->wild_table_value = true;
338 }
339 break;
340 default:
341 /*
342 The "default" is for queries over I_S.
343 All previous cases handle SHOW commands.
344 */
345 rc = calc_lookup_values_from_cond(cond, tables, lookup_field_values);
346 break;
347 }
348
349 if (lower_case_table_names && !rc) {
350 /*
351 We can safely do in-place upgrades here since all of the above cases
352 are allocating a new memory buffer for these strings.
353 */
354 if (lookup_field_values->db_value && !lookup_field_values->db_value->empty())
355 casedn(system_charset_info, *lookup_field_values->db_value);
356 if (lookup_field_values->table_value && !lookup_field_values->table_value->empty())
357 casedn(system_charset_info, *lookup_field_values->table_value);
358 }
359
360 return rc;
361}
362
363/*----------------------------------------------------------------------------*/
364
365static bool is_special_db(const dd::String_type &db_name)
366{
367 /* I_S does not exist and we hide P_S */
368 return is_infoschema_db(db_name.c_str(), db_name.size())
369 || is_perfschema_db(db_name.c_str(), db_name.size());
370}
371
372static int
373make_db_list(THD *thd, std::vector<dd::String_type> *db_names,
374 LOOKUP_FIELD_VALUES *lookup_field_vals)
375{
376 /*
377 If we have db lookup value we just add it to list and
378 exit from the function.
379 We don't do this for database names longer than the maximum
380 path length.
381 */
382 if (lookup_field_vals->db_value
383 && lookup_field_vals->db_value->length() <= NAME_LEN)
384 {
385 const dd::String_type &db_name = lookup_field_vals->db_value.get();
386 if (!is_special_db(db_name))
387 db_names->push_back(db_name);
388 return 0;
389 }
390
391 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
392 std::vector<const dd::Schema *> schemas;
393 if (thd->dd_client()->fetch_global_components(&schemas))
394 return 1;
395
396 for (const dd::Schema *schema_obj : schemas)
397 {
398 const dd::String_type &db_name = schema_obj->name();
399 if (is_special_db(db_name))
400 continue;
401 db_names->push_back(db_name);
402 }
403 return 0;
404}
405
406/*----------------------------------------------------------------------------*/
407
408/*
409 SYNOPSIS
410 thd thread handler
411 tables put found tables and their size in this list
412 db database name to set in TABLE_LIST structure
413 path path to database
414 wild filter for found files
415
416 RETURN
417 FIND_FILES_OK success
418 FIND_FILES_OOM out of memory error
419 FIND_FILES_DIR no such directory, or directory can't be read
420*/
421typedef std::map<dd::String_type, size_t> Table_sizes_map;
422static find_files_result
423find_tables(THD *thd, Table_sizes_map &tables, const char *db,
424 const char *path, boost::optional<dd::String_type> &wild,
425 MEM_ROOT *tmp_mem_root)
426{
427 MY_DIR *dirp;
428 MEM_ROOT **save_mem_root_ptr = THR_MALLOC;
429 uint col_access = thd->col_access;
430 DBUG_ENTER("find_files");
431
432 if (!(dirp = my_dir(path, MYF(MY_WANT_STAT))))
433 {
434 if (my_errno() == ENOENT)
435 my_error(ER_BAD_DB_ERROR, MYF(0), db);
436 else
437 {
438 char errbuf[MYSYS_STRERROR_SIZE];
439 my_error(ER_CANT_READ_DIR, MYF(0), path,
440 my_errno(), my_strerror(errbuf, sizeof(errbuf), my_errno()));
441 }
442 DBUG_RETURN(FIND_FILES_DIR);
443 }
444
445 if (tmp_mem_root)
446 THR_MALLOC = &tmp_mem_root;
447
448 char uname[NAME_LEN + 1]; /* Unencoded name */
449 dd::String_type fts_schema_name, fts_table_name; /* FTS lookup */
450 std::map<dd::Object_id, dd::String_type> fts_cache;
451 tables.clear();
452 for (uint i = 0; i < dirp->number_off_files; i++)
453 {
454
455 FILEINFO *file = dirp->dir_entry + i;
456 /* skip '.', '..' and temp files. */
457 if ((file->name[0] == '.' &&
458 (!file->name[1] || (file->name[1] == '.' && !file->name[2])))
459 || is_prefix(file->name, tmp_file_prefix))
460 continue;
461
462 char *ext;
463 if ((ext = strrchr(file->name, '.')))
464 {
465 // sdi files are small and their name is truncated
466 // lookup by id is possible but not worth the effort
467 if (!strcmp(ext, dd::sdi_file::EXT.c_str()))
468 continue;
469 *ext = 0;
470 ++ext;
471 }
472
473 size_t file_name_len;
474 fts_aux_table_t fts_table;
475 if (ext && !strcmp(ext, "ibd")
476 && fts_is_aux_table_name(&fts_table, file->name, strlen(file->name)))
477 {
478 auto entry = fts_cache.find(fts_table.parent_id);
479 if (entry != fts_cache.end())
480 fts_table_name = entry->second;
481 else if (thd->dd_client()->get_table_name_by_se_private_id("InnoDB",
482 fts_table.parent_id, &fts_schema_name, &fts_table_name))
483 continue;
484
485 file_name_len = (my_stpnmov(uname, fts_table_name.c_str(), sizeof(uname)) - uname);
486 }
487 else
488 file_name_len = filename_to_tablename(file->name, uname, sizeof(uname));
489
490 auto table_data = tables.find(uname);
491 if (table_data != tables.end())
492 {
493 table_data->second += file->mystat->st_size;
494 continue;
495 }
496
497 if (wild)
498 {
499 if (lower_case_table_names)
500 {
501 if (my_wildcmp(files_charset_info,
502 uname, uname + file_name_len,
503 wild->c_str(), wild->c_str() + wild->length(),
504 wild_prefix, wild_one, wild_many))
505 continue;
506 }
507 else if (wild_compare(uname, file_name_len, wild->c_str(), wild->length(), 0))
508 continue;
509 }
510
511 /* Don't show tables where we don't have any privileges */
512 if (db && !(col_access & TABLE_ACLS))
513 {
514 TABLE_LIST table_list;
515 table_list.db = db;
516 table_list.db_length = strlen(db);
517 table_list.table_name = uname;
518 table_list.table_name_length = file_name_len;
519 table_list.grant.privilege = col_access;
520 if (check_grant(thd, TABLE_ACLS, &table_list, true, 1, true))
521 continue;
522 }
523
524 tables.emplace(uname, file->mystat->st_size);
525 }
526
527 DBUG_PRINT("info", ("found: %ld files", tables.size()));
528 my_dirend(dirp);
529
530 if (tmp_mem_root)
531 THR_MALLOC = save_mem_root_ptr;
532
533 DBUG_RETURN(FIND_FILES_OK);
534}
535
536static int
537make_table_list(THD *thd, Table_sizes_map &table_names, LEX *lex,
538 LOOKUP_FIELD_VALUES *lookup_field_vals, const dd::String_type &db_name,
539 MEM_ROOT *tmp_mem_root)
540{
541 char path[FN_REFLEN + 1];
542 build_table_filename(path, sizeof(path) - 1, db_name.c_str(), "", "", 0);
543
544 const dd::Schema *sch_obj = NULL;
545 if (thd->dd_client()->acquire(db_name.c_str(), &sch_obj))
546 return 1;
547 if (!sch_obj)
548 {
549 /*
550 Report missing database only if it is a 'SHOW' command.
551 Another thread may have dropped the database after we
552 got its name from the DD.
553 */
554 if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
555 {
556 my_error(ER_BAD_DB_ERROR, MYF(0), db_name.c_str());
557 return 1;
558 }
559 return 2;
560 }
561
562 find_files_result res = find_tables(thd, table_names, db_name.c_str(), path,
563 lookup_field_vals->table_value, tmp_mem_root);
564 return (res == FIND_FILES_OK) ? 0 : 2;
565}
566
567/*----------------------------------------------------------------------------*/
568
569static struct st_mysql_information_schema info =
570{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
571
572static ST_FIELD_INFO fields_info[] =
573{
574 {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
575 {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
576 SKIP_OPEN_TABLE},
577 {"TABLE_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
578 MY_I_S_UNSIGNED, "Table_size", SKIP_OPEN_TABLE},
579 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
580};
581
582static int fill_table(THD *thd, TABLE_LIST *tables, Item *cond)
583{
584 LEX *lex = thd->lex;
585 TABLE *table = tables->table;
586 LOOKUP_FIELD_VALUES lookup_field_vals;
587 Security_context *sctx = thd->security_context();
588 std::vector<dd::String_type> db_names;
589 int error = 1;
590
591 DBUG_ENTER("fill_table");
592
593 MEM_ROOT tmp_mem_root;
594 init_sql_alloc(key_memory_get_all_tables, &tmp_mem_root,
595 TABLE_ALLOC_BLOCK_SIZE, 0);
596
597 if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
598 {
599 error = 0;
600 goto err;
601 }
602
603#define STR_OR_NIL(S) ((S) ? (S->c_str()) : "<nil>")
604 DBUG_PRINT("INDEX VALUES", ("db_name='%s', table_name='%s'",
605 STR_OR_NIL(lookup_field_vals.db_value),
606 STR_OR_NIL(lookup_field_vals.table_value)));
607
608 if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
609 {
610 /*
611 if lookup value is empty string then
612 it's impossible table name or db name
613 */
614 if ((lookup_field_vals.db_value
615 && lookup_field_vals.db_value->empty())
616 || (lookup_field_vals.table_value
617 && lookup_field_vals.table_value->empty()))
618 {
619 error = 0;
620 goto err;
621 }
622 }
623
624 if (lookup_field_vals.db_value && !lookup_field_vals.db_value->empty()
625 && !lookup_field_vals.wild_db_value)
626 tables->has_db_lookup_value = true;
627 if (lookup_field_vals.table_value && !lookup_field_vals.table_value->empty()
628 && !lookup_field_vals.wild_table_value)
629 tables->has_table_lookup_value = true;
630
631 if (lex->is_explain())
632 {
633 /* EXPLAIN SELECT */
634 error = 0;
635 goto err;
636 }
637
638 if (make_db_list(thd, &db_names, &lookup_field_vals))
639 goto err;
640
641 for (auto &db_name : db_names)
642 {
643 bool have_db_privileges = false;
644 if (sctx->get_active_roles()->size() > 0) {
645 LEX_CSTRING const_db_name = { db_name.c_str(), db_name.size() };
646 have_db_privileges = sctx->db_acl(const_db_name) > 0 ? true : false;
647 }
648 if (!(check_access(thd, SELECT_ACL, db_name.c_str(), &thd->col_access, NULL, 0, 1)
649 || (!thd->col_access && check_grant_db(thd, db_name.c_str())))
650 || sctx->check_access(DB_ACLS | SHOW_DB_ACL, true)
651 || have_db_privileges
652 || acl_get(thd, sctx->host().str, sctx->ip().str,
653 sctx->priv_user().str, db_name.c_str(), 0))
654 {
655 // We must make sure the schema is released and unlocked in the right
656 // order. Fail if we are unable to get a meta data lock on the schema
657 // name.
658 dd::Schema_MDL_locker mdl_handler(thd);
659 if (mdl_handler.ensure_locked(db_name.c_str()))
660 goto err;
661
662 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
663 Table_sizes_map tables;
664 int res = make_table_list(thd, tables, lex, &lookup_field_vals,
665 db_name, &tmp_mem_root);
666 if (res)
667 {
668 if (res == 2) /* Not fatal error, continue */
669 continue;
670 goto err;
671 }
672
673 for (auto &table_data : tables)
674 {
675 table->field[0]->store(db_name.c_str(), db_name.size(),
676 system_charset_info);
677 table->field[1]->store(table_data.first.c_str(), table_data.first.size(),
678 system_charset_info);
679 table->field[2]->store(table_data.second, true);
680 if (schema_table_store_record(thd, table))
681 goto err;
682 }
683 }
684 }
685
686 error = 0;
687
688err:
689 free_root(&tmp_mem_root, MYF(0));
690 DBUG_RETURN(error);
691
692 return 0;
693}
694
695static int init(void *ptr)
696{
697 ST_SCHEMA_TABLE *schema_table = (ST_SCHEMA_TABLE*)ptr;
698
699 schema_table->fields_info = fields_info;
700 schema_table->fill_table = fill_table;
701 schema_table->idx_field1 = 0;
702 schema_table->idx_field2 = 1;
703 schema_table->i_s_requested_object = OPTIMIZE_I_S_TABLE;
704 return 0;
705}
706
707mysql_declare_plugin(table_sizes)
708{
709 MYSQL_INFORMATION_SCHEMA_PLUGIN,
710 &info, /* type-specific descriptor */
711 "TABLE_SIZES", /* table name */
712 "Manuel Mausz", /* author */
713 "Fast INFORMATION_SCHEMA table sizes", /* description */
714 PLUGIN_LICENSE_GPL, /* license type */
715 init, /* init function */
716 NULL,
717 NULL,
718 0x0800, /* version = 8.0 */
719 NULL, /* no status variables */
720 NULL, /* no system variables */
721 NULL, /* no reserved information */
722 0 /* no flags */
723}
724mysql_declare_plugin_end;