MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ndbinfo_sql.cpp
1 /*
2  Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 #include <ndb_opts.h>
20 #include <util/BaseString.hpp>
21 #include "../src/kernel/vm/NdbinfoTables.cpp"
22 
23 static char* opt_ndbinfo_db = (char*)"ndbinfo";
24 static char* opt_table_prefix = (char*)"ndb$";
25 
26 static
27 struct my_option
28 my_long_options[] =
29 {
30  { "database", 'd',
31  "Name of the database used by ndbinfo",
32  (uchar**) &opt_ndbinfo_db, (uchar**) &opt_ndbinfo_db, 0,
33  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
34  { "prefix", 256,
35  "Prefix to use for all virtual tables loaded from NDB",
36  (uchar**) &opt_table_prefix, (uchar**) &opt_table_prefix, 0,
37  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
38  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
39 };
40 
41 
42 struct view {
43  const char* name;
44  const char* sql;
45 } views[] =
46 {
47 #if 0
48  { "pools",
49  "SELECT node_id, b.block_name, block_instance, pool_name, "
50  "used, total, high, entry_size, cp1.param_name AS param_name1, "
51  "cp2.param_name AS param_name2, cp3.param_name AS param_name3, "
52  "cp4.param_name AS param_name4 "
53  "FROM <NDBINFO_DB>.<TABLE_PREFIX>pools p "
54  "LEFT JOIN <NDBINFO_DB>.blocks b ON p.block_number = b.block_number "
55  "LEFT JOIN <NDBINFO_DB>.config_params cp1 ON p.config_param1 = cp1.param_number "
56  "LEFT JOIN <NDBINFO_DB>.config_params cp2 ON p.config_param2 = cp2.param_number "
57  "LEFT JOIN <NDBINFO_DB>.config_params cp3 ON p.config_param3 = cp3.param_number "
58  "LEFT JOIN <NDBINFO_DB>.config_params cp4 ON p.config_param4 = cp4.param_number"
59  },
60 #endif
61  { "transporters",
62  "SELECT node_id, remote_node_id, "
63  " CASE connection_status"
64  " WHEN 0 THEN \"CONNECTED\""
65  " WHEN 1 THEN \"CONNECTING\""
66  " WHEN 2 THEN \"DISCONNECTED\""
67  " WHEN 3 THEN \"DISCONNECTING\""
68  " ELSE NULL "
69  " END AS status "
70  "FROM <NDBINFO_DB>.<TABLE_PREFIX>transporters"
71  },
72  { "logspaces",
73  "SELECT node_id, "
74  " CASE log_type"
75  " WHEN 0 THEN \"REDO\""
76  " WHEN 1 THEN \"DD-UNDO\""
77  " ELSE NULL "
78  " END AS log_type, "
79  "log_id, log_part, total, used "
80  "FROM <NDBINFO_DB>.<TABLE_PREFIX>logspaces"
81  },
82  { "logbuffers",
83  "SELECT node_id, "
84  " CASE log_type"
85  " WHEN 0 THEN \"REDO\""
86  " WHEN 1 THEN \"DD-UNDO\""
87  " ELSE \"<unknown>\" "
88  " END AS log_type, "
89  "log_id, log_part, total, used "
90  "FROM <NDBINFO_DB>.<TABLE_PREFIX>logbuffers"
91  },
92  { "resources",
93  "SELECT node_id, "
94  " CASE resource_id"
95  " WHEN 0 THEN \"RESERVED\""
96  " WHEN 1 THEN \"DISK_OPERATIONS\""
97  " WHEN 2 THEN \"DISK_RECORDS\""
98  " WHEN 3 THEN \"DATA_MEMORY\""
99  " WHEN 4 THEN \"JOBBUFFER\""
100  " WHEN 5 THEN \"FILE_BUFFERS\""
101  " WHEN 6 THEN \"TRANSPORTER_BUFFERS\""
102  " ELSE \"<unknown>\" "
103  " END AS resource_name, "
104  "reserved, used, max "
105  "FROM <NDBINFO_DB>.<TABLE_PREFIX>resources"
106  },
107  { "counters",
108  "SELECT node_id, b.block_name, block_instance, "
109  "counter_id, "
110  "CASE counter_id"
111  " WHEN 1 THEN \"ATTRINFO\""
112  " WHEN 2 THEN \"TRANSACTIONS\""
113  " WHEN 3 THEN \"COMMITS\""
114  " WHEN 4 THEN \"READS\""
115  " WHEN 5 THEN \"SIMPLE_READS\""
116  " WHEN 6 THEN \"WRITES\""
117  " WHEN 7 THEN \"ABORTS\""
118  " WHEN 8 THEN \"TABLE_SCANS\""
119  " WHEN 9 THEN \"RANGE_SCANS\""
120  " WHEN 10 THEN \"OPERATIONS\""
121  " WHEN 11 THEN \"READS_RECEIVED\""
122  " WHEN 12 THEN \"LOCAL_READS_SENT\""
123  " WHEN 13 THEN \"REMOTE_READS_SENT\""
124  " WHEN 14 THEN \"READS_NOT_FOUND\""
125  " WHEN 15 THEN \"TABLE_SCANS_RECEIVED\""
126  " WHEN 16 THEN \"LOCAL_TABLE_SCANS_SENT\""
127  " WHEN 17 THEN \"RANGE_SCANS_RECEIVED\""
128  " WHEN 18 THEN \"LOCAL_RANGE_SCANS_SENT\""
129  " WHEN 19 THEN \"REMOTE_RANGE_SCANS_SENT\""
130  " WHEN 20 THEN \"SCAN_BATCHES_RETURNED\""
131  " WHEN 21 THEN \"SCAN_ROWS_RETURNED\""
132  " WHEN 22 THEN \"PRUNED_RANGE_SCANS_RECEIVED\""
133  " WHEN 23 THEN \"CONST_PRUNED_RANGE_SCANS_RECEIVED\""
134  " ELSE \"<unknown>\" "
135  " END AS counter_name, "
136  "val "
137  "FROM <NDBINFO_DB>.<TABLE_PREFIX>counters c "
138  "LEFT JOIN <NDBINFO_DB>.blocks b "
139  "ON c.block_number = b.block_number"
140  },
141  { "nodes",
142  "SELECT node_id, "
143  "uptime, "
144  "CASE status"
145  " WHEN 0 THEN \"NOTHING\""
146  " WHEN 1 THEN \"CMVMI\""
147  " WHEN 2 THEN \"STARTING\""
148  " WHEN 3 THEN \"STARTED\""
149  " WHEN 4 THEN \"SINGLEUSER\""
150  " WHEN 5 THEN \"STOPPING_1\""
151  " WHEN 6 THEN \"STOPPING_2\""
152  " WHEN 7 THEN \"STOPPING_3\""
153  " WHEN 8 THEN \"STOPPING_4\""
154  " ELSE \"<unknown>\" "
155  " END AS status, "
156  "start_phase, "
157  "config_generation "
158  "FROM <NDBINFO_DB>.<TABLE_PREFIX>nodes"
159  },
160  { "memoryusage",
161  "SELECT node_id,"
162  " pool_name AS memory_type,"
163  " SUM(used*entry_size) AS used,"
164  " SUM(used) AS used_pages,"
165  " SUM(total*entry_size) AS total,"
166  " SUM(total) AS total_pages "
167  "FROM <NDBINFO_DB>.<TABLE_PREFIX>pools "
168  "WHERE block_number IN (248, 254) AND "
169  " (pool_name = \"Index memory\" OR pool_name = \"Data memory\") "
170  "GROUP BY node_id, memory_type"
171  },
172  { "diskpagebuffer",
173  "SELECT node_id, block_instance, "
174  "pages_written, pages_written_lcp, pages_read, log_waits, "
175  "page_requests_direct_return, page_requests_wait_queue, page_requests_wait_io "
176  "FROM <NDBINFO_DB>.<TABLE_PREFIX>diskpagebuffer"
177  }
178 };
179 
180 size_t num_views = sizeof(views)/sizeof(views[0]);
181 
182 
183 #include "../src/mgmsrv/ConfigInfo.cpp"
184 static ConfigInfo g_info;
185 static void fill_config_params(BaseString& sql)
186 {
187  const char* separator = "";
188  const ConfigInfo::ParamInfo* pinfo= NULL;
189  ConfigInfo::ParamInfoIter param_iter(g_info,
190  CFG_SECTION_NODE,
191  NODE_TYPE_DB);
192  while((pinfo= param_iter.next())) {
193  if (pinfo->_paramId == 0 || // KEY_INTERNAL
194  pinfo->_status != ConfigInfo::CI_USED)
195  continue;
196  sql.appfmt("%s(%u, \"%s\")", separator, pinfo->_paramId, pinfo->_fname);
197  separator = ", ";
198  }
199 }
200 
201 
202 #include "../src/common/debugger/BlockNames.cpp"
203 static void fill_blocks(BaseString& sql)
204 {
205  const char* separator = "";
206  for (BlockNumber i = 0; i < NO_OF_BLOCK_NAMES; i++)
207  {
208  const BlockName& bn = BlockNames[i];
209  sql.appfmt("%s(%u, \"%s\")", separator, bn.number, bn.name);
210  separator = ", ";
211  }
212 }
213 
214 struct lookup {
215  const char* name;
216  const char* columns;
217  void (*fill)(BaseString&);
218 } lookups[] =
219 {
220  { "blocks",
221  "block_number INT UNSIGNED PRIMARY KEY, "
222  "block_name VARCHAR(512)",
223  &fill_blocks
224  },
225  { "config_params",
226  "param_number INT UNSIGNED PRIMARY KEY, "
227  "param_name VARCHAR(512)",
228  &fill_config_params
229  }
230 };
231 
232 size_t num_lookups = sizeof(lookups)/sizeof(lookups[0]);
233 
234 
235 struct replace {
236  const char* tag;
237  const char* string;
238 } replaces[] =
239 {
240  {"<TABLE_PREFIX>", opt_table_prefix},
241  {"<NDBINFO_DB>", opt_ndbinfo_db},
242 };
243 
244 size_t num_replaces = sizeof(replaces)/sizeof(replaces[0]);
245 
246 
247 BaseString replace_tags(const char* str)
248 {
249  BaseString result(str);
250  for (size_t i = 0; i < num_replaces; i++)
251  {
252  Vector<BaseString> parts;
253  const char* p = result.c_str();
254  const char* tag = replaces[i].tag;
255 
256  /* Split on <tag> */
257  const char* first;
258  while((first = strstr(p, tag)))
259  {
260  BaseString part;
261  part.assign(p, first - p);
262  parts.push_back(part);
263  p = first + strlen(tag);
264  }
265  parts.push_back(p);
266 
267  /* Put back together */
268  BaseString res;
269  const char* separator = "";
270  for (unsigned j = 0; j < parts.size(); j++)
271  {
272  res.appfmt("%s%s", separator, parts[j].c_str());
273  separator = replaces[i].string;
274  }
275 
276  /* Save result from this loop */
277  result = res;
278  }
279  return result;
280 }
281 
282 static void
283 print_conditional_sql(const BaseString& sql)
284 {
285  printf("SET @str=IF(@have_ndbinfo,'%s','SET @dummy = 0');\n",
286  sql.c_str());
287  printf("PREPARE stmt FROM @str;\n");
288  printf("EXECUTE stmt;\n");
289  printf("DROP PREPARE stmt;\n\n");
290 }
291 
292 int main(int argc, char** argv){
293 
294  BaseString sql;
295  if ((handle_options(&argc, &argv, my_long_options, NULL)))
296  return 2;
297 
298  printf("#\n");
299  printf("# SQL commands for creating the tables in MySQL Server which\n");
300  printf("# are used by the NDBINFO storage engine to access system\n");
301  printf("# information and statistics from MySQL Cluster\n");
302  printf("#\n");
303 
304  printf("# Only create objects if NDBINFO is supported\n");
305  printf("SELECT @have_ndbinfo:= COUNT(*) FROM "
306  "information_schema.engines WHERE engine='NDBINFO' "
307  "AND support IN ('YES', 'DEFAULT');\n\n");
308 
309  printf("# Only create objects if version >= 7.1\n");
310  sql.assfmt("SELECT @have_ndbinfo:="
311  " (@@ndbinfo_version >= (7 << 16) | (1 << 8)) || @ndbinfo_skip_version_check");
312  print_conditional_sql(sql);
313 
314  printf("# Only create objects if ndbinfo namespace is free\n");
315  sql.assfmt("SET @@ndbinfo_show_hidden=TRUE");
316  print_conditional_sql(sql);
317  sql.assfmt("SELECT @have_ndbinfo:= COUNT(*) = 0"
318  " FROM information_schema.tables WHERE"
319  " table_schema = @@ndbinfo_database AND"
320  " LEFT(table_name, LENGTH(@@ndbinfo_table_prefix)) ="
321  " @@ndbinfo_table_prefix AND"
322  " engine != \"ndbinfo\"");
323  print_conditional_sql(sql);
324  sql.assfmt("SET @@ndbinfo_show_hidden=default");
325  print_conditional_sql(sql);
326 
327  sql.assfmt("CREATE DATABASE IF NOT EXISTS `%s`", opt_ndbinfo_db);
328  print_conditional_sql(sql);
329 
330  printf("# Set NDBINFO in offline mode during (re)create of tables\n");
331  printf("# and views to avoid errors caused by no such table or\n");
332  printf("# different table definition in NDB\n");
333  sql.assfmt("SET @@global.ndbinfo_offline=TRUE");
334  print_conditional_sql(sql);
335 
336  printf("# Drop any old views in %s\n", opt_ndbinfo_db);
337  for (size_t i = 0; i < num_views; i++)
338  {
339  sql.assfmt("DROP VIEW IF EXISTS %s.%s",
340  opt_ndbinfo_db, views[i].name);
341  print_conditional_sql(sql);
342  }
343 
344  printf("# Drop any old lookup tables in %s\n", opt_ndbinfo_db);
345  for (size_t i = 0; i < num_lookups; i++)
346  {
347  sql.assfmt("DROP TABLE IF EXISTS %s.%s",
348  opt_ndbinfo_db, lookups[i].name);
349  print_conditional_sql(sql);
350  }
351 
352  for (int i = 0; i < Ndbinfo::getNumTables(); i++)
353  {
354  const Ndbinfo::Table& table = Ndbinfo::getTable(i);
355 
356  printf("# %s.%s%s\n",
357  opt_ndbinfo_db, opt_table_prefix, table.m.name);
358 
359  /* Drop the table if it exists */
360  sql.assfmt("DROP TABLE IF EXISTS `%s`.`%s%s`",
361  opt_ndbinfo_db, opt_table_prefix, table.m.name);
362  print_conditional_sql(sql);
363 
364  /* Create the table */
365  sql.assfmt("CREATE TABLE `%s`.`%s%s` (",
366  opt_ndbinfo_db, opt_table_prefix, table.m.name);
367 
368  const char* separator = "";
369  for(int j = 0; j < table.m.ncols ; j++)
370  {
371  const Ndbinfo::Column& col = table.col[j];
372 
373  sql.appfmt("%s", separator);
374  separator = ",";
375 
376  sql.appfmt("`%s` ", col.name);
377 
378  switch(col.coltype)
379  {
380  case Ndbinfo::Number:
381  sql.appfmt("INT UNSIGNED");
382  break;
383  case Ndbinfo:: Number64:
384  sql.appfmt("BIGINT UNSIGNED");
385  break;
386  case Ndbinfo::String:
387  sql.appfmt("VARCHAR(512)");
388  break;
389  default:
390  fprintf(stderr, "unknown coltype: %d\n", col.coltype);
391  abort();
392  break;
393  }
394 
395  if (col.comment[0] != '\0')
396  sql.appfmt(" COMMENT \"%s\"", col.comment);
397 
398  }
399 
400  sql.appfmt(") COMMENT=\"%s\" ENGINE=NDBINFO", table.m.comment);
401 
402  print_conditional_sql(sql);
403 
404  }
405 
406  for (size_t i = 0; i < num_lookups; i++)
407  {
408  lookup l = lookups[i];
409  printf("# %s.%s\n", opt_ndbinfo_db, l.name);
410 
411  /* Create lookup table */
412  sql.assfmt("CREATE TABLE `%s`.`%s` (%s)",
413  opt_ndbinfo_db, l.name, l.columns);
414  print_conditional_sql(sql);
415 
416  /* Insert data */
417  sql.assfmt("INSERT INTO `%s`.`%s` VALUES ",
418  opt_ndbinfo_db, l.name);
419  l.fill(sql);
420  print_conditional_sql(sql);
421  }
422 
423  for (size_t i = 0; i < num_views; i++)
424  {
425  view v = views[i];
426 
427  printf("# %s.%s\n", opt_ndbinfo_db, v.name);
428 
429  BaseString view_sql = replace_tags(v.sql);
430 
431  /* Create or replace the view */
432  BaseString sql;
433  sql.assfmt("CREATE OR REPLACE DEFINER=`root@localhost` "
434  "SQL SECURITY INVOKER VIEW `%s`.`%s` AS %s",
435  opt_ndbinfo_db, v.name, view_sql.c_str());
436  print_conditional_sql(sql);
437  }
438 
439  printf("# Finally turn off offline mode\n");
440  sql.assfmt("SET @@global.ndbinfo_offline=FALSE");
441  print_conditional_sql(sql);
442 
443  return 0;
444 }
445