summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac68
-rw-r--r--m4/ac_mysql.m496
-rw-r--r--src/Makefile.am8
-rw-r--r--table_sizes.cc (renamed from src/table_sizes.cc)345
6 files changed, 115 insertions, 413 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e468c80..7392af9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,9 @@
1INCLUDE_DIRECTORIES(SYSTEM ${BOOST_PATCHES_DIR} ${BOOST_INCLUDE_DIR}) 1INCLUDE_DIRECTORIES(SYSTEM ${BOOST_PATCHES_DIR} ${BOOST_INCLUDE_DIR})
2 2
3MYSQL_ADD_PLUGIN(table_sizes src/table_sizes.cc 3MYSQL_ADD_PLUGIN(table_sizes
4 MODULE_ONLY MODULE_OUTPUT_NAME "table_sizes") 4 table_sizes.cc
5 MODULE_ONLY MODULE_OUTPUT_NAME "table_sizes"
6 LINK_LIBRARIES extra::rapidjson
7 )
5 8
9ADD_DEFINITIONS(-DMYSQL_SERVER)
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 3cb8f22..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
1AUTOMAKE_OPTIONS = foreign no-dependencies
2ACLOCAL_AMFLAGS = -I m4
3SUBDIRS = src
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index 48857f8..0000000
--- a/configure.ac
+++ /dev/null
@@ -1,68 +0,0 @@
1# Process this file with autoconf to produce a configure script.
2
3AC_PREREQ(2.59)
4AC_INIT(mysql-table-sizes-plugin, [dev])
5AC_CANONICAL_TARGET
6AC_CONFIG_MACRO_DIR([m4])
7
8AM_INIT_AUTOMAKE
9
10AC_CONFIG_SRCDIR([src/table_sizes.cc])
11AC_CONFIG_HEADER([src/config.h])
12
13AC_DEFUN([CHECK_DEBUG], [
14 AC_ARG_ENABLE([debug],
15 AS_HELP_STRING([--enable-debug], [turn on debugging, default: no]))
16
17 AC_MSG_CHECKING(whether to enable debugging)
18 AS_IF([test "x$enable_debug" = "xyes"],
19 [
20 CPPFLAGS="$CPPFLAGS -g -D_DEBUG"
21 AC_MSG_RESULT(yes)
22 ],
23 [
24 CPPFLAGS="$CPPFLAGS -g -O2 -DDBUG_OFF"
25 AC_MSG_RESULT(no)
26 ]
27 )
28])
29
30
31dnl Run tests using C++ compiler
32dnl AC_LANG(C++)
33
34CHECK_DEBUG
35
36#check for mysql src
37MYSQL_SRC_TEST
38MYSQL_PLUGIN_DIR_TEST
39#MYSQL_LIB_SERVICES_TEST
40AC_SUBST(MYSQL_INC)
41AC_SUBST(MYSQL_PLUGIN_DIR)
42#AC_SUBST(MYSQL_LIBSERVICES)
43
44#check for programs
45AC_PROG_CC
46AC_PROG_LIBTOOL
47AC_PROG_CXX
48AC_PROG_CPP
49
50#we can add the following flags for better error catching: -Werror
51CPPFLAGS="$CPPFLAGS -Werror"
52# From MySQL: Disable exceptions as they seams to create problems with gcc and threads.
53CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-rtti"
54
55#make sure we have const
56AC_C_CONST
57AC_TYPE_SIZE_T
58
59#subst the relevant variables
60AC_SUBST(CPPFLAGS)
61AC_SUBST(CXXLAGS)
62AC_SUBST(CFLAGS)
63
64AC_CONFIG_FILES([
65 Makefile
66 src/Makefile
67])
68AC_OUTPUT
diff --git a/m4/ac_mysql.m4 b/m4/ac_mysql.m4
deleted file mode 100644
index b5a5c0c..0000000
--- a/m4/ac_mysql.m4
+++ /dev/null
@@ -1,96 +0,0 @@
1dnl ---------------------------------------------------------------------------
2dnl Macro: MYSQL_SRC_TEST
3dnl ---------------------------------------------------------------------------
4
5dir_resolve() dnl {{{
6{
7 pwd=`pwd`
8 cd "$1" 2>/dev/null || cd "${pwd}/${1}" 2>/dev/null
9 if test "$?" = "0"
10 then
11 echo `pwd -P`
12 else
13 echo "$1"
14 fi
15}
16dnl }}}
17
18AC_DEFUN([MYSQL_SRC_TEST], [
19 AC_MSG_CHECKING(for mysql source code)
20 AC_ARG_WITH(mysql,
21 [AS_HELP_STRING([--with-mysql=PATH], [MySQL src directory required to build.])],
22 [
23 ac_mysql_source_dir=`readlink -e "$withval"`
24 HEADERS="include/my_dir.h include/mysql/plugin.h include/mysql.h include/mysql_version.h include/config.h include/my_config.h"
25 for file in $HEADERS
26 do
27 if ! test -r "$ac_mysql_source_dir/$file"
28 then
29 AC_MSG_ERROR([Failed to find required header file $ac_mysql_source_dir/$file, check the path and make sure you've run './configure ..<options>.. && cd include && make' in MySQL 5.1 sources dir or 'cmake . && make' in MySQL 5.5 sources dir.])
30 fi
31 done
32 AC_DEFINE([MYSQL_SRC], [1], [Source directory for MySQL])
33 MYSQL_INC="-I$ac_mysql_source_dir/sql -I$ac_mysql_source_dir/include -I$ac_mysql_source_dir/regex -I$ac_mysql_source_dir -I$ac_mysql_source_dir/libbinlogevents/export -I$ac_mysql_source_dir/libbinlogevents/include -I$ac_mysql_source_dir/sql/auth"
34 AC_MSG_RESULT(["$ac_mysql_source_dir"])
35 ],
36 [
37 AC_MSG_ERROR(["No mysql source provided. Please specify --with-mysql=<mysql source dir>!"])
38 ]
39 )
40])
41
42dnl ---------------------------------------------------------------------------
43dnl Macro: MYSQL_PLUGIN_DIR_TEST
44dnl ---------------------------------------------------------------------------
45
46AC_DEFUN([MYSQL_PLUGIN_DIR_TEST], [
47 AC_MSG_CHECKING([for mysql plugin dir])
48 ac_mysql_plugin_dir=
49 AC_ARG_WITH([mysql-plugindir],
50 [AS_HELP_STRING([--with-mysql-plugindir=PATH], [MySQL plugin directory where plugin is to be copied to])],
51 [
52 ac_mysql_plugin_dir=`readlink -m "$withval"`
53 MYSQL_PLUGIN_DIR="$ac_mysql_plugin_dir"
54 ],
55 [
56 ac_mysql_plugin_dir="/usr/lib/mysql/plugin"
57 MYSQL_PLUGIN_DIR="$ac_mysql_plugin_dir"
58 AC_MSG_RESULT([--with-mysql-plugindir was not set. Using $ac_mysql_plugin_dir])
59 ]
60 )
61])
62
63dnl ---------------------------------------------------------------------------
64dnl Macro: MYSQL_LIB_SERVICES : 5.5 services lib to add to linker
65dnl ---------------------------------------------------------------------------
66
67dnl AC_DEFUN([MYSQL_LIB_SERVICES_TEST], [
68dnl AC_MSG_CHECKING([for mysql libmysqlservices])
69dnl ac_mysql_libservices=
70dnl AC_ARG_WITH([mysql-libservices],
71dnl [AS_HELP_STRING([--with-mysql-libservices=PATH], [MySQL libmysqlservices.a location (relevant for 5.5 only)])],
72dnl [
73dnl ac_mysql_libservices=`readlink -e "$withval"`
74dnl if test -f "$ac_mysql_libservices"
75dnl then
76dnl MYSQL_LIBSERVICES="$ac_mysql_libservices"
77dnl AC_MSG_RESULT([yes: Using $ac_mysql_libservices])
78dnl else
79dnl AC_MSG_ERROR([invalid MySQL libmysqlservices : $ac_mysql_libservices])
80dnl fi
81dnl ],
82dnl [
83dnl if test -f "$ac_mysql_source_dir/VERSION"
84dnl then
85dnl source "$ac_mysql_source_dir/VERSION"
86dnl if test "$MYSQL_VERSION_MAJOR.$MYSQL_VERSION_MINOR" = "5.5"
87dnl then
88dnl AC_MSG_ERROR([no mysql-libservices. Required for MySQL 5.5])
89dnl fi
90dnl fi
91dnl ac_mysql_libservices=""
92dnl MYSQL_LIBSERVICES="$ac_mysql_libservices"
93dnl AC_MSG_RESULT([--with-mysql-libservices was not set.])
94dnl ]
95dnl )
96dnl ])
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/table_sizes.cc
index 40d5090..ec8efc0 100644
--- a/src/table_sizes.cc
+++ b/table_sizes.cc
@@ -18,10 +18,9 @@
18 18
19#include "sql/mysqld.h" 19#include "sql/mysqld.h"
20#include "sql/sql_base.h" 20#include "sql/sql_base.h"
21#include "sql/sql_show.h"
22#include "sql/sql_class.h" // THD 21#include "sql/sql_class.h" // THD
23#include "sql/sql_table.h" // filename_to_tablename 22#include "sql/sql_table.h" // filename_to_tablename
24#include "sql/strfunc.h" // make_lex_string_root 23#include "sql/strfunc.h" // casedn
25#include "sql/sql_parse.h" // sql_command_flags 24#include "sql/sql_parse.h" // sql_command_flags
26#include "sql/sql_lex.h" // LEX 25#include "sql/sql_lex.h" // LEX
27#include "sql/item_func.h" // Item_Func 26#include "sql/item_func.h" // Item_Func
@@ -156,25 +155,13 @@ struct LOOKUP_FIELD_VALUES {
156 /** 155 /**
157 Value of a TABLE_SCHEMA clause. 156 Value of a TABLE_SCHEMA clause.
158 Note that this value length may exceed @c NAME_LEN. 157 Note that this value length may exceed @c NAME_LEN.
159 @sa wild_db_value
160 */ 158 */
161 boost::optional<dd::String_type> db_value; 159 boost::optional<dd::String_type> db_value;
162 /** 160 /**
163 Value of a TABLE_NAME clause. 161 Value of a TABLE_NAME clause.
164 Note that this value length may exceed @c NAME_LEN. 162 Note that this value length may exceed @c NAME_LEN.
165 @sa wild_table_value
166 */ 163 */
167 boost::optional<dd::String_type> table_value; 164 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}; 165};
179 166
180/** 167/**
@@ -195,19 +182,11 @@ struct LOOKUP_FIELD_VALUES {
195 1 error, there can be no matching records for the condition 182 1 error, there can be no matching records for the condition
196*/ 183*/
197 184
198static bool get_lookup_value(Item_func *item_func, TABLE_LIST *table, 185static bool get_lookup_value(Item_func *item_func, Table_ref *table,
199 LOOKUP_FIELD_VALUES *lookup_field_vals) 186 LOOKUP_FIELD_VALUES *lookup_field_vals)
200{ 187{
201 ST_SCHEMA_TABLE *schema_table = table->schema_table; 188 ST_SCHEMA_TABLE *schema_table = table->schema_table;
202 ST_FIELD_INFO *field_info = schema_table->fields_info; 189 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 190
212 if (item_func->functype() == Item_func::EQ_FUNC || 191 if (item_func->functype() == Item_func::EQ_FUNC ||
213 item_func->functype() == Item_func::EQUAL_FUNC) { 192 item_func->functype() == Item_func::EQUAL_FUNC) {
@@ -236,15 +215,16 @@ static bool get_lookup_value(Item_func *item_func, TABLE_LIST *table,
236 if (!tmp_str) return 1; 215 if (!tmp_str) return 1;
237 216
238 /* Lookup value is database name */ 217 /* Lookup value is database name */
239 if (!cs->coll->strnncollsp(cs, (uchar *)field_name1, strlen(field_name1), 218 if (!cs->coll->strnncollsp(cs, (const uchar *)field_info[0].field_name,
240 (uchar *)item_field->field_name, 219 strlen(field_info[0].field_name),
220 (const uchar *)item_field->field_name,
241 strlen(item_field->field_name))) { 221 strlen(item_field->field_name))) {
242 lookup_field_vals->db_value.emplace(tmp_str->ptr(), tmp_str->length()); 222 lookup_field_vals->db_value.emplace(tmp_str->ptr(), tmp_str->length());
243 } 223 }
244 /* Lookup value is table name */ 224 /* Lookup value is table name */
245 else if (!cs->coll->strnncollsp(cs, (uchar *)field_name2, 225 else if (!cs->coll->strnncollsp(cs, (const uchar *)field_info[1].field_name,
246 strlen(field_name2), 226 strlen(field_info[1].field_name),
247 (uchar *)item_field->field_name, 227 (const uchar *)item_field->field_name,
248 strlen(item_field->field_name))) { 228 strlen(item_field->field_name))) {
249 lookup_field_vals->table_value.emplace(tmp_str->ptr(), tmp_str->length()); 229 lookup_field_vals->table_value.emplace(tmp_str->ptr(), tmp_str->length());
250 } 230 }
@@ -270,7 +250,7 @@ static bool get_lookup_value(Item_func *item_func, TABLE_LIST *table,
270*/ 250*/
271 251
272static bool calc_lookup_values_from_cond(Item *cond, 252static bool calc_lookup_values_from_cond(Item *cond,
273 TABLE_LIST *table, LOOKUP_FIELD_VALUES *lookup_field_vals) 253 Table_ref *table, LOOKUP_FIELD_VALUES *lookup_field_vals)
274{ 254{
275 if (!cond) return 0; 255 if (!cond) return 0;
276 256
@@ -299,62 +279,32 @@ static bool calc_lookup_values_from_cond(Item *cond,
299 @brief Calculate lookup values(database name, table name) 279 @brief Calculate lookup values(database name, table name)
300 280
301 @details This function calculates lookup values(database name, table name) 281 @details This function calculates lookup values(database name, table name)
302 from 'WHERE' condition or wild values (for 'SHOW' commands only) 282 from 'WHERE' condition and fill lookup_field_vals struct field
303 from LEX struct and fill lookup_field_vals struct field
304 with these values. 283 with these values.
305 284
306 @param[in] thd thread handler 285 @param[in] cond WHERE condition
307 @param[in] cond WHERE condition 286 @param[in] tables I_S table
308 @param[in] tables I_S table 287 @param[in, out] lookup_field_vals Struct which holds lookup values
309 @param[in, out] lookup_field_values Struct which holds lookup values
310 288
311 @return 289 @return
312 0 success 290 0 success
313 1 error, there can be no matching records for the condition 291 1 error, there can be no matching records for the condition
314*/ 292*/
315 293
316static bool get_lookup_field_values(THD *thd, Item *cond, TABLE_LIST *tables, 294static bool get_lookup_field_values(Item *cond, Table_ref *tables,
317 LOOKUP_FIELD_VALUES *lookup_field_values) 295 LOOKUP_FIELD_VALUES *lookup_field_vals)
318{ 296{
319 LEX *lex = thd->lex; 297 bool rc = calc_lookup_values_from_cond(cond, tables, lookup_field_vals);
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 298
349 if (lower_case_table_names && !rc) { 299 if (lower_case_table_names && !rc) {
350 /* 300 /*
351 We can safely do in-place upgrades here since all of the above cases 301 We can safely do in-place upgrades here since all of the above cases
352 are allocating a new memory buffer for these strings. 302 are allocating a new memory buffer for these strings.
353 */ 303 */
354 if (lookup_field_values->db_value && !lookup_field_values->db_value->empty()) 304 if (lookup_field_vals->db_value && !lookup_field_vals->db_value->empty())
355 casedn(system_charset_info, *lookup_field_values->db_value); 305 casedn(system_charset_info, *lookup_field_vals->db_value);
356 if (lookup_field_values->table_value && !lookup_field_values->table_value->empty()) 306 if (lookup_field_vals->table_value && !lookup_field_vals->table_value->empty())
357 casedn(system_charset_info, *lookup_field_values->table_value); 307 casedn(system_charset_info, *lookup_field_vals->table_value);
358 } 308 }
359 309
360 return rc; 310 return rc;
@@ -369,8 +319,16 @@ static bool is_special_db(const dd::String_type &db_name)
369 || is_perfschema_db(db_name.c_str(), db_name.size()); 319 || is_perfschema_db(db_name.c_str(), db_name.size());
370} 320}
371 321
372static int 322/**
373make_db_list(THD *thd, std::vector<dd::String_type> *db_names, 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,
374 LOOKUP_FIELD_VALUES *lookup_field_vals) 332 LOOKUP_FIELD_VALUES *lookup_field_vals)
375{ 333{
376 /* 334 /*
@@ -405,53 +363,45 @@ make_db_list(THD *thd, std::vector<dd::String_type> *db_names,
405 363
406/*----------------------------------------------------------------------------*/ 364/*----------------------------------------------------------------------------*/
407 365
408/* 366/**
409 SYNOPSIS 367 Find files in a given directory.
410 thd thread handler 368
411 tables put found tables and their size in this list 369 @param thd thread handler
412 db database name to set in TABLE_LIST structure 370 @param tables put found files in this list
413 path path to database 371 @param db_name filter for found files
414 wild filter for found files 372 @param wild filter for found files
415 373
416 RETURN 374 @return true if error, false otherwise
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*/ 375*/
421typedef std::map<dd::String_type, size_t> Table_sizes_map; 376typedef std::map<dd::String_type, size_t> Table_sizes_map;
422static find_files_result 377bool find_tables(THD *thd, Table_sizes_map &tables,
423find_tables(THD *thd, Table_sizes_map &tables, const char *db, 378 Table_ref &db_data, boost::optional<dd::String_type> &wild)
424 const char *path, boost::optional<dd::String_type> &wild,
425 MEM_ROOT *tmp_mem_root)
426{ 379{
427 MY_DIR *dirp; 380 MY_DIR *dirp;
428 MEM_ROOT **save_mem_root_ptr = THR_MALLOC;
429 uint col_access = thd->col_access;
430 DBUG_ENTER("find_files"); 381 DBUG_ENTER("find_files");
431 382
383 char path[FN_REFLEN + 1];
384 build_table_filename(path, sizeof(path) - 1, db_data.db, "", "", 0);
385
432 if (!(dirp = my_dir(path, MYF(MY_WANT_STAT)))) 386 if (!(dirp = my_dir(path, MYF(MY_WANT_STAT))))
433 { 387 {
434 if (my_errno() == ENOENT) 388 if (my_errno() == ENOENT)
435 my_error(ER_BAD_DB_ERROR, MYF(0), db); 389 my_error(ER_BAD_DB_ERROR, MYF(0), db_data.db);
436 else 390 else
437 { 391 {
438 char errbuf[MYSYS_STRERROR_SIZE]; 392 char errbuf[MYSYS_STRERROR_SIZE];
439 my_error(ER_CANT_READ_DIR, MYF(0), path, 393 my_error(ER_CANT_READ_DIR, MYF(0), path,
440 my_errno(), my_strerror(errbuf, sizeof(errbuf), my_errno())); 394 my_errno(), my_strerror(errbuf, sizeof(errbuf), my_errno()));
441 } 395 }
442 DBUG_RETURN(FIND_FILES_DIR); 396 return true;
443 } 397 }
444 398
445 if (tmp_mem_root)
446 THR_MALLOC = &tmp_mem_root;
447
448 char uname[NAME_LEN + 1]; /* Unencoded name */ 399 char uname[NAME_LEN + 1]; /* Unencoded name */
449 dd::String_type fts_schema_name, fts_table_name; /* FTS lookup */ 400 dd::String_type fts_schema_name, fts_table_name; /* FTS lookup */
450 std::map<dd::Object_id, dd::String_type> fts_cache; 401 std::map<dd::Object_id, dd::String_type> fts_cache;
451 tables.clear(); 402 tables.clear();
452 for (uint i = 0; i < dirp->number_off_files; i++) 403 for (uint i = 0; i < dirp->number_off_files; i++)
453 { 404 {
454
455 FILEINFO *file = dirp->dir_entry + i; 405 FILEINFO *file = dirp->dir_entry + i;
456 /* skip '.', '..' and temp files. */ 406 /* skip '.', '..' and temp files. */
457 if ((file->name[0] == '.' && 407 if ((file->name[0] == '.' &&
@@ -508,18 +458,14 @@ find_tables(THD *thd, Table_sizes_map &tables, const char *db,
508 continue; 458 continue;
509 } 459 }
510 460
511 /* Don't show tables where we don't have any privileges */ 461 /*
512 if (db && !(col_access & TABLE_ACLS)) 462 Check_grant will grant access if there is any column privileges on
513 { 463 all of the tables thanks to the fourth parameter (bool show_table).
514 TABLE_LIST table_list; 464 */
515 table_list.db = db; 465 db_data.table_name = uname;
516 table_list.db_length = strlen(db); 466 db_data.table_name_length = file_name_len;
517 table_list.table_name = uname; 467 if (check_grant(thd, SELECT_ACL, &db_data, true, 1, true))
518 table_list.table_name_length = file_name_len; 468 continue;
519 table_list.grant.privilege = col_access;
520 if (check_grant(thd, TABLE_ACLS, &table_list, true, 1, true))
521 continue;
522 }
523 469
524 tables.emplace(uname, file->mystat->st_size); 470 tables.emplace(uname, file->mystat->st_size);
525 } 471 }
@@ -527,167 +473,94 @@ find_tables(THD *thd, Table_sizes_map &tables, const char *db,
527 DBUG_PRINT("info", ("found: %ld files", tables.size())); 473 DBUG_PRINT("info", ("found: %ld files", tables.size()));
528 my_dirend(dirp); 474 my_dirend(dirp);
529 475
530 if (tmp_mem_root) 476 return false;
531 THR_MALLOC = save_mem_root_ptr;
532
533 DBUG_RETURN(FIND_FILES_OK);
534} 477}
535 478
536static int 479static bool make_table_list(THD *thd, Table_sizes_map &table_names,
537make_table_list(THD *thd, Table_sizes_map &table_names, LEX *lex, 480 LOOKUP_FIELD_VALUES *lookup_field_vals, Table_ref &db_data)
538 LOOKUP_FIELD_VALUES *lookup_field_vals, const dd::String_type &db_name,
539 MEM_ROOT *tmp_mem_root)
540{ 481{
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; 482 const dd::Schema *sch_obj = NULL;
545 if (thd->dd_client()->acquire(db_name.c_str(), &sch_obj)) 483 if (thd->dd_client()->acquire(db_data.db, &sch_obj) || !sch_obj)
546 return 1; 484 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 485
562 find_files_result res = find_tables(thd, table_names, db_name.c_str(), path, 486 return find_tables(thd, table_names, db_data, lookup_field_vals->table_value);
563 lookup_field_vals->table_value, tmp_mem_root);
564 return (res == FIND_FILES_OK) ? 0 : 2;
565} 487}
566 488
567/*----------------------------------------------------------------------------*/ 489/*----------------------------------------------------------------------------*/
568 490
569static struct st_mysql_information_schema info =
570{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
571
572static ST_FIELD_INFO fields_info[] = 491static ST_FIELD_INFO fields_info[] =
573{ 492{
574 {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, 493 {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, 0},
575 {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name", 494 {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name", 0},
576 SKIP_OPEN_TABLE},
577 {"TABLE_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 495 {"TABLE_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
578 MY_I_S_UNSIGNED, "Table_size", SKIP_OPEN_TABLE}, 496 MY_I_S_UNSIGNED, "Table_size", 0},
579 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} 497 {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
580}; 498};
581 499
582static int fill_table(THD *thd, TABLE_LIST *tables, Item *cond) 500static int fill_table(THD *thd, Table_ref *tables, Item *cond)
583{ 501{
584 LEX *lex = thd->lex;
585 TABLE *table = tables->table; 502 TABLE *table = tables->table;
586 LOOKUP_FIELD_VALUES lookup_field_vals; 503 LOOKUP_FIELD_VALUES lookup_field_vals;
587 Security_context *sctx = thd->security_context();
588 std::vector<dd::String_type> db_names; 504 std::vector<dd::String_type> db_names;
589 int error = 1;
590 505
591 DBUG_ENTER("fill_table"); 506 DBUG_ENTER("fill_table");
592 507
593 MEM_ROOT tmp_mem_root; 508 if (get_lookup_field_values(cond, tables, &lookup_field_vals))
594 init_sql_alloc(key_memory_get_all_tables, &tmp_mem_root, 509 return 0;
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 510
603#define STR_OR_NIL(S) ((S) ? (S->c_str()) : "<nil>") 511#define STR_OR_NIL(S) ((S) ? (S->c_str()) : "<nil>")
604 DBUG_PRINT("INDEX VALUES", ("db_name='%s', table_name='%s'", 512 DBUG_PRINT("INDEX VALUES", ("db_name='%s', table_name='%s'",
605 STR_OR_NIL(lookup_field_vals.db_value), 513 STR_OR_NIL(lookup_field_vals.db_value),
606 STR_OR_NIL(lookup_field_vals.table_value))); 514 STR_OR_NIL(lookup_field_vals.table_value)));
607 515
608 if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value) 516 /* EXPLAIN SELECT */
609 { 517 if (thd->lex->is_explain())
610 /* 518 return 0;
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 519
638 if (make_db_list(thd, &db_names, &lookup_field_vals)) 520 if (make_db_list(thd, &db_names, &lookup_field_vals))
639 goto err; 521 return 1;
640 522
641 for (auto &db_name : db_names) 523 for (auto &db_name : db_names)
642 { 524 {
643 bool have_db_privileges = false; 525 Table_ref db_data;
644 if (sctx->get_active_roles()->size() > 0) { 526 memset(reinterpret_cast<char *>(&db_data), 0, sizeof(db_data));
645 LEX_CSTRING const_db_name = { db_name.c_str(), db_name.size() }; 527 db_data.db = db_name.c_str();
646 have_db_privileges = sctx->db_acl(const_db_name) > 0 ? true : false; 528 db_data.db_length = db_name.length();
647 } 529 db_data.grant.privilege = 0;
648 if (!(check_access(thd, SELECT_ACL, db_name.c_str(), &thd->col_access, NULL, 0, 1) 530
649 || (!thd->col_access && check_grant_db(thd, db_name.c_str()))) 531 // Get user's global and db-level privileges.
650 || sctx->check_access(DB_ACLS | SHOW_DB_ACL, true) 532 if (check_access(thd, SELECT_ACL, db_data.db, &db_data.grant.privilege, NULL, false, true))
651 || have_db_privileges 533 continue;
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 534
673 for (auto &table_data : tables) 535 // Now check, if user has access on global level or to any of database/
674 { 536 // table/column/routine.
675 table->field[0]->store(db_name.c_str(), db_name.size(), 537 if (!(db_data.grant.privilege & DB_OP_ACLS) && check_grant_db(thd, db_data.db))
676 system_charset_info); 538 continue;
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 539
686 error = 0; 540 // We must make sure the schema is released and unlocked in the right
541 // order. Fail if we are unable to get a meta data lock on the schema
542 // name.
543 dd::Schema_MDL_locker mdl_handler(thd);
544 if (mdl_handler.ensure_locked(db_data.db))
545 return 1;
687 546
688err: 547 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
689 free_root(&tmp_mem_root, MYF(0)); 548 Table_sizes_map tables_data;
690 DBUG_RETURN(error); 549 int res = make_table_list(thd, tables_data, &lookup_field_vals, db_data);
550 if (res)
551 continue;
552
553 for (auto &table_data : tables_data)
554 {
555 table->field[0]->store(db_data.db, db_data.db_length,
556 system_charset_info);
557 table->field[1]->store(table_data.first.c_str(), table_data.first.size(),
558 system_charset_info);
559 table->field[2]->store(table_data.second, true);
560 if (schema_table_store_record(thd, table))
561 return 1;
562 }
563 }
691 564
692 return 0; 565 return 0;
693} 566}
@@ -698,12 +571,12 @@ static int init(void *ptr)
698 571
699 schema_table->fields_info = fields_info; 572 schema_table->fields_info = fields_info;
700 schema_table->fill_table = fill_table; 573 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; 574 return 0;
705} 575}
706 576
577static struct st_mysql_information_schema info =
578{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
579
707mysql_declare_plugin(table_sizes) 580mysql_declare_plugin(table_sizes)
708{ 581{
709 MYSQL_INFORMATION_SCHEMA_PLUGIN, 582 MYSQL_INFORMATION_SCHEMA_PLUGIN,