~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Monty Taylor
  • Date: 2010-03-06 02:08:13 UTC
  • mto: This revision was merged to the branch mainline in revision 1381.
  • Revision ID: mordred@inaugust.com-20100306020813-c37d0b39004nl1zf
Remove plugin deinit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2010 Brian Aker
5
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
6
5
 *
7
6
 *  This program is free software; you can redistribute it and/or modify
8
7
 *  it under the terms of the GNU General Public License as published by
20
19
 
21
20
 
22
21
/* Function with list databases, tables or fields */
23
 
#include <config.h>
24
 
 
 
22
#include "config.h"
 
23
#include <drizzled/sql_select.h>
 
24
#include <drizzled/show.h>
 
25
#include <drizzled/gettext.h>
 
26
#include <drizzled/util/convert.h>
 
27
#include <drizzled/error.h>
 
28
#include <drizzled/tztime.h>
25
29
#include <drizzled/data_home.h>
26
 
#include <drizzled/error.h>
27
 
#include <drizzled/internal/my_sys.h>
28
 
#include <drizzled/plugin/storage_engine.h>
29
 
#include <drizzled/session.h>
30
 
#include <drizzled/show.h>
31
 
#include <drizzled/sql_select.h>
32
 
 
33
 
#include <drizzled/statement/show.h>
34
 
#include <drizzled/statement/show_errors.h>
35
 
#include <drizzled/statement/show_warnings.h>
36
 
 
 
30
#include <drizzled/item/blob.h>
 
31
#include <drizzled/item/cmpfunc.h>
 
32
#include <drizzled/item/return_int.h>
 
33
#include <drizzled/item/empty_string.h>
 
34
#include <drizzled/item/return_date_time.h>
 
35
#include <drizzled/sql_base.h>
 
36
#include <drizzled/db.h>
 
37
#include <drizzled/field/timestamp.h>
 
38
#include <drizzled/field/decimal.h>
 
39
#include <drizzled/lock.h>
 
40
#include <drizzled/item/return_date_time.h>
 
41
#include <drizzled/item/empty_string.h>
 
42
#include "drizzled/plugin/registry.h"
 
43
#include "drizzled/session_list.h"
 
44
#include <drizzled/message/schema.pb.h>
 
45
#include <drizzled/plugin/client.h>
 
46
#include <drizzled/cached_directory.h>
 
47
#include "drizzled/sql_table.h"
 
48
#include "drizzled/global_charset_info.h"
 
49
#include "drizzled/pthread_globals.h"
 
50
#include "drizzled/internal/m_string.h"
 
51
#include "drizzled/internal/my_sys.h"
37
52
 
38
53
#include <sys/stat.h>
39
54
 
54
69
  return str ? str : "<nil>";
55
70
}
56
71
 
57
 
int wild_case_compare(const charset_info_st * const cs, const char *str, const char *wildstr)
 
72
static void store_key_options(String *packet, Table *table, KEY *key_info);
 
73
 
 
74
 
 
75
int wild_case_compare(const CHARSET_INFO * const cs, const char *str, const char *wildstr)
58
76
{
59
77
  register int flag;
60
78
 
64
82
    {
65
83
      if (*wildstr == internal::wild_prefix && wildstr[1])
66
84
        wildstr++;
67
 
 
68
85
      if (my_toupper(cs, *wildstr++) != my_toupper(cs, *str++))
69
86
        return (1);
70
87
    }
71
 
 
72
88
    if (! *wildstr )
73
89
      return (*str != 0);
74
 
 
75
90
    if (*wildstr++ == internal::wild_one)
76
91
    {
77
92
      if (! *str++)
81
96
    {                                           /* Found '*' */
82
97
      if (! *wildstr)
83
98
        return (0);             /* '*' as last char: OK */
84
 
 
85
99
      flag=(*wildstr != internal::wild_many && *wildstr != internal::wild_one);
86
100
      do
87
101
      {
90
104
          char cmp;
91
105
          if ((cmp= *wildstr) == internal::wild_prefix && wildstr[1])
92
106
            cmp= wildstr[1];
93
 
 
94
107
          cmp= my_toupper(cs, cmp);
95
 
 
96
108
          while (*str && my_toupper(cs, *str) != cmp)
97
109
            str++;
98
 
 
99
110
          if (! *str)
100
111
            return (1);
101
112
        }
102
 
 
103
113
        if (wild_case_compare(cs, str, wildstr) == 0)
104
114
          return (0);
105
 
 
106
115
      } while (*str++);
107
 
 
108
116
      return (1);
109
117
    }
110
118
  }
112
120
  return (*str != '\0');
113
121
}
114
122
 
 
123
 
 
124
bool drizzled_show_create(Session *session, TableList *table_list, bool is_if_not_exists)
 
125
{
 
126
  char buff[2048];
 
127
  String buffer(buff, sizeof(buff), system_charset_info);
 
128
 
 
129
  /* Only one table for now, but VIEW can involve several tables */
 
130
  if (session->openTables(table_list))
 
131
  {
 
132
    if (session->is_error())
 
133
      return true;
 
134
 
 
135
    /*
 
136
      Clear all messages with 'error' level status and
 
137
      issue a warning with 'warning' level status in
 
138
      case of invalid view and last error is ER_VIEW_INVALID
 
139
    */
 
140
    drizzle_reset_errors(session, true);
 
141
    session->clear_error();
 
142
  }
 
143
 
 
144
  buffer.length(0);
 
145
 
 
146
  if (store_create_info(table_list, &buffer, is_if_not_exists))
 
147
    return true;
 
148
 
 
149
  List<Item> field_list;
 
150
  {
 
151
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
 
152
    // 1024 is for not to confuse old clients
 
153
    field_list.push_back(new Item_empty_string("Create Table",
 
154
                                               max(buffer.length(),(uint32_t)1024)));
 
155
  }
 
156
 
 
157
  if (session->client->sendFields(&field_list))
 
158
    return true;
 
159
  {
 
160
    session->client->store(table_list->table->alias);
 
161
  }
 
162
 
 
163
  session->client->store(buffer.ptr(), buffer.length());
 
164
 
 
165
  if (session->client->flush())
 
166
    return true;
 
167
 
 
168
  session->my_eof();
 
169
  return false;
 
170
}
 
171
 
 
172
/**
 
173
  Get a CREATE statement for a given database.
 
174
 
 
175
  The database is identified by its name, passed as @c dbname parameter.
 
176
  The name should be encoded using the system character set (UTF8 currently).
 
177
 
 
178
  Resulting statement is stored in the string pointed by @c buffer. The string
 
179
  is emptied first and its character set is set to the system character set.
 
180
 
 
181
  If is_if_not_exists is set, then
 
182
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
 
183
  in @c create_options are ignored.
 
184
 
 
185
  @param  session           The current thread instance.
 
186
  @param  dbname        The name of the database.
 
187
  @param  buffer        A String instance where the statement is stored.
 
188
  @param  create_info   If not NULL, the options member influences the resulting
 
189
                        CRATE statement.
 
190
 
 
191
  @returns true if errors are detected, false otherwise.
 
192
*/
 
193
 
 
194
static bool store_db_create_info(const char *dbname, string &buffer, bool if_not_exists)
 
195
{
 
196
  message::Schema schema;
 
197
 
 
198
  bool found= plugin::StorageEngine::getSchemaDefinition(dbname, schema);
 
199
  if (not found)
 
200
    return false;
 
201
 
 
202
  buffer.append("CREATE DATABASE ");
 
203
 
 
204
  if (if_not_exists)
 
205
    buffer.append("IF NOT EXISTS ");
 
206
 
 
207
  buffer.append("`");
 
208
  buffer.append(schema.name());
 
209
  buffer.append("`");
 
210
 
 
211
  if (schema.has_collation())
 
212
  {
 
213
    buffer.append(" COLLATE = ");
 
214
    buffer.append(schema.collation());
 
215
  }
 
216
 
 
217
  return true;
 
218
}
 
219
 
 
220
bool mysqld_show_create_db(Session *session, const char *dbname, bool if_not_exists)
 
221
{
 
222
  string buffer;
 
223
 
 
224
  if (not store_db_create_info(dbname, buffer, if_not_exists))
 
225
  {
 
226
    /*
 
227
      This assumes that the only reason for which store_db_create_info()
 
228
      can fail is incorrect database name (which is the case now).
 
229
    */
 
230
    my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
 
231
    return true;
 
232
  }
 
233
 
 
234
  List<Item> field_list;
 
235
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
 
236
  field_list.push_back(new Item_empty_string("Create Database",1024));
 
237
 
 
238
  if (session->client->sendFields(&field_list))
 
239
    return true;
 
240
 
 
241
  session->client->store(dbname, strlen(dbname));
 
242
  session->client->store(buffer);
 
243
 
 
244
  if (session->client->flush())
 
245
    return true;
 
246
 
 
247
  session->my_eof();
 
248
 
 
249
  return false;
 
250
}
 
251
 
115
252
/*
116
253
  Get the quote character for displaying an identifier.
117
254
 
137
274
  return '`';
138
275
}
139
276
 
140
 
namespace show {
141
 
 
142
 
bool buildScemas(Session *session)
143
 
{
144
 
  session->getLex()->sql_command= SQLCOM_SELECT;
145
 
  session->getLex()->statement= new statement::Show(session);
146
 
 
147
 
  std::string column_name= "Database";
148
 
  if (session->getLex()->wild)
149
 
  {
150
 
    column_name.append(" (");
151
 
    column_name.append(session->getLex()->wild->ptr());
152
 
    column_name.append(")");
153
 
  }
154
 
 
155
 
  if (session->getLex()->current_select->where)
156
 
  {
157
 
    if (prepare_new_schema_table(session, session->getLex(), "SCHEMAS"))
158
 
      return false;
159
 
  }
160
 
  else
161
 
  {
162
 
    if (prepare_new_schema_table(session, session->getLex(), "SHOW_SCHEMAS"))
163
 
      return false;
164
 
  }
165
 
 
166
 
  Item_field *my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "SCHEMA_NAME");
167
 
  my_field->is_autogenerated_name= false;
168
 
  my_field->set_name(column_name.c_str(), column_name.length(), system_charset_info);
169
 
 
170
 
  if (session->add_item_to_list(my_field))
171
 
    return false;
172
 
 
173
 
  if (session->add_order_to_list(my_field, true))
174
 
    return false;
175
 
 
176
 
  return true;
177
 
}
178
 
 
179
 
bool buildTables(Session *session, const char *ident)
180
 
{
181
 
  session->getLex()->sql_command= SQLCOM_SELECT;
182
 
 
183
 
  drizzled::statement::Show *select= new statement::Show(session);
184
 
  session->getLex()->statement= select;
185
 
 
186
 
  std::string column_name= "Tables_in_";
187
 
 
188
 
  util::string::const_shared_ptr schema(session->schema());
189
 
  if (ident)
190
 
  {
191
 
    identifier::Schema identifier(ident);
192
 
    column_name.append(ident);
193
 
    session->getLex()->select_lex.db= const_cast<char *>(ident);
194
 
    if (not plugin::StorageEngine::doesSchemaExist(identifier))
195
 
    {
196
 
      my_error(ER_BAD_DB_ERROR, identifier);
197
 
    }
198
 
    select->setShowPredicate(ident, "");
199
 
  }
200
 
  else if (schema and not schema->empty())
201
 
  {
202
 
    column_name.append(*schema);
203
 
    select->setShowPredicate(*schema, "");
204
 
  }
205
 
  else
206
 
  {
207
 
    my_error(ER_NO_DB_ERROR, MYF(0));
208
 
    return false;
209
 
  }
210
 
 
211
 
 
212
 
  if (session->getLex()->wild)
213
 
  {
214
 
    column_name.append(" (");
215
 
    column_name.append(session->getLex()->wild->ptr());
216
 
    column_name.append(")");
217
 
  }
218
 
 
219
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_TABLES"))
220
 
    return false;
221
 
 
222
 
  Item_field *my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "TABLE_NAME");
223
 
  my_field->is_autogenerated_name= false;
224
 
  my_field->set_name(column_name.c_str(), column_name.length(), system_charset_info);
225
 
 
226
 
  if (session->add_item_to_list(my_field))
227
 
    return false;
228
 
 
229
 
  if (session->add_order_to_list(my_field, true))
230
 
    return false;
231
 
 
232
 
  return true;
233
 
}
234
 
 
235
 
bool buildTemporaryTables(Session *session)
236
 
{
237
 
  session->getLex()->sql_command= SQLCOM_SELECT;
238
 
 
239
 
  session->getLex()->statement= new statement::Show(session);
240
 
 
241
 
 
242
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_TEMPORARY_TABLES"))
243
 
    return false;
244
 
 
245
 
  if (session->add_item_to_list( new Item_field(&session->getLex()->current_select->context, NULL, NULL, "*")))
246
 
    return false;
247
 
 
248
 
  (session->getLex()->current_select->with_wild)++;
249
 
 
250
 
  return true;
251
 
}
252
 
 
253
 
bool buildTableStatus(Session *session, const char *ident)
254
 
{
255
 
  session->getLex()->sql_command= SQLCOM_SELECT;
256
 
  drizzled::statement::Show *select= new statement::Show(session);
257
 
  session->getLex()->statement= select;
258
 
 
259
 
  std::string column_name= "Tables_in_";
260
 
 
261
 
  util::string::const_shared_ptr schema(session->schema());
262
 
  if (ident)
263
 
  {
264
 
    session->getLex()->select_lex.db= const_cast<char *>(ident);
265
 
 
266
 
    identifier::Schema identifier(ident);
267
 
    if (not plugin::StorageEngine::doesSchemaExist(identifier))
268
 
    {
269
 
      my_error(ER_BAD_DB_ERROR, identifier);
270
 
    }
271
 
 
272
 
    select->setShowPredicate(ident, "");
273
 
  }
274
 
  else if (schema)
275
 
  {
276
 
    select->setShowPredicate(*schema, "");
277
 
  }
278
 
  else
279
 
  {
280
 
    my_error(ER_NO_DB_ERROR, MYF(0));
281
 
    return false;
282
 
  }
283
 
 
284
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_TABLE_STATUS"))
285
 
    return false;
286
 
 
287
 
  if (session->add_item_to_list( new Item_field(&session->getLex()->current_select->
288
 
                                                  context,
289
 
                                                  NULL, NULL, "*")))
290
 
    return false;
291
 
 
292
 
  (session->getLex()->current_select->with_wild)++;
293
 
 
294
 
  return true;
295
 
}
296
 
 
297
 
bool buildEngineStatus(Session *session, LEX_STRING)
298
 
{
299
 
  session->getLex()->sql_command= SQLCOM_SELECT;
300
 
  drizzled::statement::Show *select= new statement::Show(session);
301
 
  session->getLex()->statement= select;
302
 
 
303
 
  my_error(ER_USE_DATA_DICTIONARY);
304
 
  return false;
305
 
}
306
 
 
307
 
bool buildColumns(Session *session, const char *schema_ident, Table_ident *table_ident)
308
 
{
309
 
  session->getLex()->sql_command= SQLCOM_SELECT;
310
 
 
311
 
  drizzled::statement::Show *select= new statement::Show(session);
312
 
  session->getLex()->statement= select;
313
 
 
314
 
  util::string::const_shared_ptr schema(session->schema());
315
 
  if (schema_ident)
316
 
  {
317
 
    select->setShowPredicate(schema_ident, table_ident->table.str);
318
 
  }
319
 
  else if (table_ident->db.str)
320
 
  {
321
 
    select->setShowPredicate(table_ident->db.str, table_ident->table.str);
322
 
  }
323
 
  else if (schema)
324
 
  {
325
 
    select->setShowPredicate(*schema, table_ident->table.str);
326
 
  }
327
 
  else
328
 
  {
329
 
    my_error(ER_NO_DB_ERROR, MYF(0));
330
 
    return false;
331
 
  }
332
 
 
333
 
  {
334
 
    drizzled::identifier::Table identifier(select->getShowSchema().c_str(), table_ident->table.str);
335
 
    if (not plugin::StorageEngine::doesTableExist(*session, identifier))
336
 
    {
337
 
      my_error(ER_TABLE_UNKNOWN, identifier);
338
 
    }
339
 
  }
340
 
 
341
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_COLUMNS"))
342
 
    return false;
343
 
 
344
 
  if (session->add_item_to_list( new Item_field(&session->getLex()->current_select->context, NULL, NULL, "*")))
345
 
    return false;
346
 
 
347
 
  (session->getLex()->current_select->with_wild)++;
348
 
 
349
 
  return true;
350
 
}
351
 
 
352
 
void buildSelectWarning(Session *session)
353
 
{
354
 
  (void) create_select_for_variable(session, "warning_count");
355
 
  session->getLex()->statement= new statement::Show(session);
356
 
}
357
 
 
358
 
void buildSelectError(Session *session)
359
 
{
360
 
  (void) create_select_for_variable(session, "error_count");
361
 
  session->getLex()->statement= new statement::Show(session);
362
 
}
363
 
 
364
 
void buildWarnings(Session *session)
365
 
{
366
 
  session->getLex()->statement= new statement::ShowWarnings(session);
367
 
}
368
 
 
369
 
void buildErrors(Session *session)
370
 
{
371
 
  session->getLex()->statement= new statement::ShowErrors(session);
372
 
}
373
 
 
374
 
bool buildIndex(Session *session, const char *schema_ident, Table_ident *table_ident)
375
 
{
376
 
  session->getLex()->sql_command= SQLCOM_SELECT;
377
 
  drizzled::statement::Show *select= new statement::Show(session);
378
 
  session->getLex()->statement= select;
379
 
 
380
 
  util::string::const_shared_ptr schema(session->schema());
381
 
  if (schema_ident)
382
 
  {
383
 
    select->setShowPredicate(schema_ident, table_ident->table.str);
384
 
  }
385
 
  else if (table_ident->db.str)
386
 
  {
387
 
    select->setShowPredicate(table_ident->db.str, table_ident->table.str);
388
 
  }
389
 
  else if (schema)
390
 
  {
391
 
    select->setShowPredicate(*schema, table_ident->table.str);
392
 
  }
393
 
  else
394
 
  {
395
 
    my_error(ER_NO_DB_ERROR, MYF(0));
396
 
    return false;
397
 
  }
398
 
 
399
 
  {
400
 
    drizzled::identifier::Table identifier(select->getShowSchema().c_str(), table_ident->table.str);
401
 
    if (not plugin::StorageEngine::doesTableExist(*session, identifier))
402
 
    {
403
 
      my_error(ER_TABLE_UNKNOWN, identifier);
404
 
    }
405
 
  }
406
 
 
407
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_INDEXES"))
408
 
    return false;
409
 
 
410
 
  if (session->add_item_to_list( new Item_field(&session->getLex()->current_select->context, NULL, NULL, "*")))
411
 
    return false;
412
 
 
413
 
  (session->getLex()->current_select->with_wild)++;
414
 
 
415
 
  return true;
416
 
}
417
 
 
418
 
bool buildStatus(Session *session, const drizzled::sql_var_t is_global)
419
 
{
420
 
  session->getLex()->sql_command= SQLCOM_SELECT;
421
 
  session->getLex()->statement= new statement::Show(session);
422
 
 
423
 
  if (is_global == OPT_GLOBAL)
424
 
  {
425
 
    if (prepare_new_schema_table(session, session->getLex(), "GLOBAL_STATUS"))
426
 
      return false;
427
 
  }
428
 
  else
429
 
  {
430
 
    if (prepare_new_schema_table(session, session->getLex(), "SESSION_STATUS"))
431
 
      return false;
432
 
  }
433
 
 
434
 
  std::string key("Variable_name");
435
 
  std::string value("Value");
436
 
 
437
 
  Item_field *my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "VARIABLE_NAME");
438
 
  my_field->is_autogenerated_name= false;
439
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
440
 
 
441
 
  if (session->add_item_to_list(my_field))
442
 
    return false;
443
 
 
444
 
  my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "VARIABLE_VALUE");
445
 
  my_field->is_autogenerated_name= false;
446
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
447
 
 
448
 
  if (session->add_item_to_list(my_field))
449
 
    return false;
450
 
 
451
 
  return true;
452
 
}
453
 
 
454
 
bool buildCreateTable(Session *session, Table_ident *ident)
455
 
{
456
 
  session->getLex()->sql_command= SQLCOM_SELECT;
457
 
  statement::Show *select= new statement::Show(session);
458
 
  session->getLex()->statement= select;
459
 
 
460
 
  if (session->getLex()->statement == NULL)
461
 
    return false;
462
 
 
463
 
  if (prepare_new_schema_table(session, session->getLex(), "TABLE_SQL_DEFINITION"))
464
 
    return false;
465
 
 
466
 
  util::string::const_shared_ptr schema(session->schema());
467
 
  if (ident->db.str)
468
 
  {
469
 
    select->setShowPredicate(ident->db.str, ident->table.str);
470
 
  }
471
 
  else if (schema)
472
 
  {
473
 
    select->setShowPredicate(*schema, ident->table.str);
474
 
  }
475
 
  else
476
 
  {
477
 
    my_error(ER_NO_DB_ERROR, MYF(0));
478
 
    return false;
479
 
  }
480
 
 
481
 
  std::string key("Table");
482
 
  std::string value("Create Table");
483
 
 
484
 
  Item_field *my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "TABLE_NAME");
485
 
  my_field->is_autogenerated_name= false;
486
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
487
 
 
488
 
  if (session->add_item_to_list(my_field))
489
 
    return false;
490
 
 
491
 
  my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "TABLE_SQL_DEFINITION");
492
 
  my_field->is_autogenerated_name= false;
493
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
494
 
 
495
 
  if (session->add_item_to_list(my_field))
496
 
    return false;
497
 
 
498
 
  return true;
499
 
}
500
 
 
501
 
bool buildProcesslist(Session *session)
502
 
{
503
 
  session->getLex()->sql_command= SQLCOM_SELECT;
504
 
  session->getLex()->statement= new statement::Show(session);
505
 
 
506
 
  if (prepare_new_schema_table(session, session->getLex(), "PROCESSLIST"))
507
 
    return false;
508
 
 
509
 
  if (session->add_item_to_list( new Item_field(&session->getLex()->current_select->context, NULL, NULL, "*")))
510
 
    return false;
511
 
 
512
 
  (session->getLex()->current_select->with_wild)++;
513
 
 
514
 
  return true;
515
 
}
516
 
 
517
 
bool buildVariables(Session *session, const drizzled::sql_var_t is_global)
518
 
{
519
 
  session->getLex()->sql_command= SQLCOM_SELECT;
520
 
  session->getLex()->statement= new statement::Show(session);
521
 
 
522
 
  if (is_global == OPT_GLOBAL)
523
 
  {
524
 
    if (prepare_new_schema_table(session, session->getLex(), "GLOBAL_VARIABLES"))
525
 
      return false;
526
 
  }
527
 
  else
528
 
  {
529
 
    if (prepare_new_schema_table(session, session->getLex(), "SESSION_VARIABLES"))
530
 
      return false;
531
 
  }
532
 
 
533
 
  std::string key("Variable_name");
534
 
  std::string value("Value");
535
 
 
536
 
  Item_field *my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "VARIABLE_NAME");
537
 
  my_field->is_autogenerated_name= false;
538
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
539
 
 
540
 
  if (session->add_item_to_list(my_field))
541
 
    return false;
542
 
 
543
 
  my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "VARIABLE_VALUE");
544
 
  my_field->is_autogenerated_name= false;
545
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
546
 
 
547
 
  if (session->add_item_to_list(my_field))
548
 
    return false;
549
 
 
550
 
  return true;
551
 
}
552
 
 
553
 
bool buildCreateSchema(Session *session, LEX_STRING &ident)
554
 
{
555
 
  session->getLex()->sql_command= SQLCOM_SELECT;
556
 
  drizzled::statement::Show *select= new statement::Show(session);
557
 
  session->getLex()->statement= select;
558
 
 
559
 
  if (prepare_new_schema_table(session, session->getLex(), "SCHEMA_SQL_DEFINITION"))
560
 
    return false;
561
 
 
562
 
  util::string::const_shared_ptr schema(session->schema());
563
 
  if (ident.str)
564
 
  {
565
 
    select->setShowPredicate(ident.str);
566
 
  }
567
 
  else if (schema)
568
 
  {
569
 
    select->setShowPredicate(*schema);
570
 
  }
571
 
  else
572
 
  {
573
 
    my_error(ER_NO_DB_ERROR, MYF(0));
574
 
    return false;
575
 
  }
576
 
 
577
 
  std::string key("Database");
578
 
  std::string value("Create Database");
579
 
 
580
 
  Item_field *my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "SCHEMA_NAME");
581
 
  my_field->is_autogenerated_name= false;
582
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
583
 
 
584
 
  if (session->add_item_to_list(my_field))
585
 
    return false;
586
 
 
587
 
  my_field= new Item_field(&session->getLex()->current_select->context, NULL, NULL, "SCHEMA_SQL_DEFINITION");
588
 
  my_field->is_autogenerated_name= false;
589
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
590
 
 
591
 
  if (session->add_item_to_list(my_field))
592
 
    return false;
593
 
 
594
 
  return true;
595
 
}
596
 
 
597
 
bool buildDescribe(Session *session, Table_ident *ident)
598
 
{
599
 
  session->getLex()->lock_option= TL_READ;
600
 
  init_select(session->getLex());
601
 
  session->getLex()->current_select->parsing_place= SELECT_LIST;
602
 
  session->getLex()->sql_command= SQLCOM_SELECT;
603
 
  drizzled::statement::Show *select= new statement::Show(session);
604
 
  session->getLex()->statement= select;
605
 
  session->getLex()->select_lex.db= 0;
606
 
 
607
 
  util::string::const_shared_ptr schema(session->schema());
608
 
  if (ident->db.str)
609
 
  {
610
 
    select->setShowPredicate(ident->db.str, ident->table.str);
611
 
  }
612
 
  else if (schema)
613
 
  {
614
 
    select->setShowPredicate(*schema, ident->table.str);
615
 
  }
616
 
  else
617
 
  {
618
 
    my_error(ER_NO_DB_ERROR, MYF(0));
619
 
    return false;
620
 
  }
621
 
 
622
 
  {
623
 
    drizzled::identifier::Table identifier(select->getShowSchema().c_str(), ident->table.str);
624
 
    if (not plugin::StorageEngine::doesTableExist(*session, identifier))
625
 
    {
626
 
      my_error(ER_TABLE_UNKNOWN, identifier);
627
 
    }
628
 
  }
629
 
 
630
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_COLUMNS"))
631
 
  {
632
 
    return false;
633
 
  }
634
 
 
635
 
  if (session->add_item_to_list( new Item_field(&session->getLex()->current_select->
636
 
                                                  context,
637
 
                                                  NULL, NULL, "*")))
638
 
  {
639
 
    return false;
640
 
  }
641
 
 
642
 
  (session->getLex()->current_select->with_wild)++;
643
 
 
644
 
  return true;
645
 
}
646
 
 
647
 
} /* namespace drizzled */
 
277
 
 
278
#define LIST_PROCESS_HOST_LEN 64
 
279
 
 
280
static bool get_field_default_value(Field *timestamp_field,
 
281
                                    Field *field, String *def_value,
 
282
                                    bool quoted)
 
283
{
 
284
  bool has_default;
 
285
  bool has_now_default;
 
286
 
 
287
  /*
 
288
     We are using CURRENT_TIMESTAMP instead of NOW because it is
 
289
     more standard
 
290
  */
 
291
  has_now_default= (timestamp_field == field &&
 
292
                    field->unireg_check != Field::TIMESTAMP_UN_FIELD);
 
293
 
 
294
  has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
 
295
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
 
296
                field->unireg_check != Field::NEXT_NUMBER);
 
297
 
 
298
  def_value->length(0);
 
299
  if (has_default)
 
300
  {
 
301
    if (has_now_default)
 
302
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
 
303
    else if (!field->is_null())
 
304
    {                                             // Not null by default
 
305
      char tmp[MAX_FIELD_WIDTH];
 
306
      String type(tmp, sizeof(tmp), field->charset());
 
307
      field->val_str(&type);
 
308
      if (type.length())
 
309
      {
 
310
        String def_val;
 
311
        uint32_t dummy_errors;
 
312
        /* convert to system_charset_info == utf8 */
 
313
        def_val.copy(type.ptr(), type.length(), field->charset(),
 
314
                     system_charset_info, &dummy_errors);
 
315
        if (quoted)
 
316
          append_unescaped(def_value, def_val.ptr(), def_val.length());
 
317
        else
 
318
          def_value->append(def_val.ptr(), def_val.length());
 
319
      }
 
320
      else if (quoted)
 
321
        def_value->append(STRING_WITH_LEN("''"));
 
322
    }
 
323
    else if (field->maybe_null() && quoted)
 
324
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
 
325
    else
 
326
      return false;
 
327
  }
 
328
  return has_default;
 
329
}
 
330
 
 
331
/*
 
332
  Build a CREATE TABLE statement for a table.
 
333
 
 
334
  SYNOPSIS
 
335
    store_create_info()
 
336
    table_list        A list containing one table to write statement
 
337
                      for.
 
338
    packet            Pointer to a string where statement will be
 
339
                      written.
 
340
 
 
341
  NOTE
 
342
    Currently always return 0, but might return error code in the
 
343
    future.
 
344
 
 
345
  RETURN
 
346
    0       OK
 
347
 */
 
348
 
 
349
int store_create_info(TableList *table_list, String *packet, bool is_if_not_exists)
 
350
{
 
351
  List<Item> field_list;
 
352
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
 
353
  const char *alias;
 
354
  string buff;
 
355
  String type(tmp, sizeof(tmp), system_charset_info);
 
356
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
 
357
  Field **ptr,*field;
 
358
  uint32_t primary_key;
 
359
  KEY *key_info;
 
360
  Table *table= table_list->table;
 
361
  Cursor *cursor= table->cursor;
 
362
  TableShare *share= table->s;
 
363
  HA_CREATE_INFO create_info;
 
364
  bool show_table_options= false;
 
365
  my_bitmap_map *old_map;
 
366
 
 
367
  table->restoreRecordAsDefault(); // Get empty record
 
368
 
 
369
  if (share->tmp_table)
 
370
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
 
371
  else
 
372
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
 
373
  if (is_if_not_exists)
 
374
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
375
  alias= share->table_name.str;
 
376
 
 
377
  packet->append_identifier(alias, strlen(alias));
 
378
  packet->append(STRING_WITH_LEN(" (\n"));
 
379
  /*
 
380
    We need this to get default values from the table
 
381
    We have to restore the read_set if we are called from insert in case
 
382
    of row based replication.
 
383
  */
 
384
  old_map= table->use_all_columns(table->read_set);
 
385
 
 
386
  for (ptr=table->field ; (field= *ptr); ptr++)
 
387
  {
 
388
    uint32_t flags = field->flags;
 
389
 
 
390
    if (ptr != table->field)
 
391
      packet->append(STRING_WITH_LEN(",\n"));
 
392
 
 
393
    packet->append(STRING_WITH_LEN("  "));
 
394
    packet->append_identifier(field->field_name, strlen(field->field_name));
 
395
    packet->append(' ');
 
396
    // check for surprises from the previous call to Field::sql_type()
 
397
    if (type.ptr() != tmp)
 
398
      type.set(tmp, sizeof(tmp), system_charset_info);
 
399
    else
 
400
      type.set_charset(system_charset_info);
 
401
 
 
402
    field->sql_type(type);
 
403
    packet->append(type.ptr(), type.length(), system_charset_info);
 
404
 
 
405
    if (field->has_charset())
 
406
    {
 
407
      if (field->charset() != share->table_charset)
 
408
      {
 
409
        packet->append(STRING_WITH_LEN(" CHARACTER SET "));
 
410
        packet->append(field->charset()->csname);
 
411
      }
 
412
 
 
413
      /*
 
414
        For string types dump collation name only if
 
415
        collation is not primary for the given charset
 
416
      */
 
417
      if (!(field->charset()->state & MY_CS_PRIMARY))
 
418
      {
 
419
        packet->append(STRING_WITH_LEN(" COLLATE "));
 
420
        packet->append(field->charset()->name);
 
421
      }
 
422
    }
 
423
 
 
424
    if (flags & NOT_NULL_FLAG)
 
425
      packet->append(STRING_WITH_LEN(" NOT NULL"));
 
426
    else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
427
    {
 
428
      /*
 
429
        TIMESTAMP field require explicit NULL flag, because unlike
 
430
        all other fields they are treated as NOT NULL by default.
 
431
      */
 
432
      packet->append(STRING_WITH_LEN(" NULL"));
 
433
    }
 
434
    {
 
435
      /*
 
436
        Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
 
437
        and about STORAGE (DISK or MEMORY).
 
438
      */
 
439
      enum column_format_type column_format= (enum column_format_type)
 
440
        ((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
441
      if (column_format)
 
442
      {
 
443
        packet->append(STRING_WITH_LEN(" /*!"));
 
444
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
 
445
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
 
446
          packet->append(STRING_WITH_LEN(" FIXED */"));
 
447
        else
 
448
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
 
449
      }
 
450
    }
 
451
    if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
 
452
    {
 
453
      packet->append(STRING_WITH_LEN(" DEFAULT "));
 
454
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
 
455
    }
 
456
 
 
457
    if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
458
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
 
459
 
 
460
    if (field->unireg_check == Field::NEXT_NUMBER)
 
461
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
 
462
 
 
463
    if (field->comment.length)
 
464
    {
 
465
      packet->append(STRING_WITH_LEN(" COMMENT "));
 
466
      append_unescaped(packet, field->comment.str, field->comment.length);
 
467
    }
 
468
  }
 
469
 
 
470
  key_info= table->key_info;
 
471
  memset(&create_info, 0, sizeof(create_info));
 
472
  /* Allow update_create_info to update row type */
 
473
  create_info.row_type= share->row_type;
 
474
  cursor->update_create_info(&create_info);
 
475
  primary_key= share->primary_key;
 
476
 
 
477
  for (uint32_t i=0 ; i < share->keys ; i++,key_info++)
 
478
  {
 
479
    KEY_PART_INFO *key_part= key_info->key_part;
 
480
    bool found_primary=0;
 
481
    packet->append(STRING_WITH_LEN(",\n  "));
 
482
 
 
483
    if (i == primary_key && is_primary_key(key_info))
 
484
    {
 
485
      found_primary=1;
 
486
      /*
 
487
        No space at end, because a space will be added after where the
 
488
        identifier would go, but that is not added for primary key.
 
489
      */
 
490
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
 
491
    }
 
492
    else if (key_info->flags & HA_NOSAME)
 
493
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
 
494
    else
 
495
      packet->append(STRING_WITH_LEN("KEY "));
 
496
 
 
497
    if (!found_primary)
 
498
     packet->append_identifier(key_info->name, strlen(key_info->name));
 
499
 
 
500
    packet->append(STRING_WITH_LEN(" ("));
 
501
 
 
502
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
503
    {
 
504
      if (j)
 
505
        packet->append(',');
 
506
 
 
507
      if (key_part->field)
 
508
        packet->append_identifier(key_part->field->field_name,
 
509
                                  strlen(key_part->field->field_name));
 
510
      if (key_part->field &&
 
511
          (key_part->length !=
 
512
           table->field[key_part->fieldnr-1]->key_length()))
 
513
      {
 
514
        buff.assign("(");
 
515
        buff.append(to_string((int32_t) key_part->length /
 
516
                              key_part->field->charset()->mbmaxlen));
 
517
        buff.append(")");
 
518
        packet->append(buff.c_str(), buff.length());
 
519
      }
 
520
    }
 
521
    packet->append(')');
 
522
    store_key_options(packet, table, key_info);
 
523
  }
 
524
 
 
525
  /*
 
526
    Get possible foreign key definitions stored in InnoDB and append them
 
527
    to the CREATE TABLE statement
 
528
  */
 
529
 
 
530
  if ((for_str= cursor->get_foreign_key_create_info()))
 
531
  {
 
532
    packet->append(for_str, strlen(for_str));
 
533
    cursor->free_foreign_key_create_info(for_str);
 
534
  }
 
535
 
 
536
  packet->append(STRING_WITH_LEN("\n)"));
 
537
  {
 
538
    show_table_options= true;
 
539
    /*
 
540
      Get possible table space definitions and append them
 
541
      to the CREATE TABLE statement
 
542
    */
 
543
 
 
544
    /* 
 
545
      We should always store engine since we will now be 
 
546
      making sure engines accept options (aka... no
 
547
      dangling arguments for engines.
 
548
    */
 
549
    packet->append(STRING_WITH_LEN(" ENGINE="));
 
550
    packet->append(cursor->engine->getName().c_str());
 
551
 
 
552
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
 
553
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
 
554
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
 
555
      packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
 
556
    if (create_info.row_type != ROW_TYPE_DEFAULT)
 
557
    {
 
558
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
 
559
      packet->append(ha_row_type[(uint32_t) create_info.row_type]);
 
560
    }
 
561
    if (table->s->hasKeyBlockSize())
 
562
    {
 
563
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
564
      buff= to_string(table->s->getKeyBlockSize());
 
565
      packet->append(buff.c_str(), buff.length());
 
566
    }
 
567
    if (share->block_size)
 
568
    {
 
569
      packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
 
570
      buff= to_string(share->block_size);
 
571
      packet->append(buff.c_str(), buff.length());
 
572
    }
 
573
    table->cursor->append_create_info(packet);
 
574
    if (share->hasComment() && share->getCommentLength())
 
575
    {
 
576
      packet->append(STRING_WITH_LEN(" COMMENT="));
 
577
      append_unescaped(packet, share->getComment(),
 
578
                       share->getCommentLength());
 
579
    }
 
580
  }
 
581
  table->restore_column_map(old_map);
 
582
  return(0);
 
583
}
 
584
 
 
585
static void store_key_options(String *packet, Table *table, KEY *key_info)
 
586
{
 
587
  char *end, buff[32];
 
588
 
 
589
  if (key_info->algorithm == HA_KEY_ALG_BTREE)
 
590
    packet->append(STRING_WITH_LEN(" USING BTREE"));
 
591
 
 
592
  if (key_info->algorithm == HA_KEY_ALG_HASH)
 
593
    packet->append(STRING_WITH_LEN(" USING HASH"));
 
594
 
 
595
  if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
 
596
      table->s->getKeyBlockSize() != key_info->block_size)
 
597
  {
 
598
    packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
599
    end= internal::int64_t10_to_str(key_info->block_size, buff, 10);
 
600
    packet->append(buff, (uint32_t) (end - buff));
 
601
  }
 
602
 
 
603
  assert(test(key_info->flags & HA_USES_COMMENT) ==
 
604
              (key_info->comment.length > 0));
 
605
  if (key_info->flags & HA_USES_COMMENT)
 
606
  {
 
607
    packet->append(STRING_WITH_LEN(" COMMENT "));
 
608
    append_unescaped(packet, key_info->comment.str,
 
609
                     key_info->comment.length);
 
610
  }
 
611
}
 
612
 
 
613
 
 
614
/****************************************************************************
 
615
  Return info about all processes
 
616
  returns for each thread: thread id, user, host, db, command, info
 
617
****************************************************************************/
 
618
 
 
619
class thread_info
 
620
{
 
621
  thread_info();
 
622
public:
 
623
  uint64_t thread_id;
 
624
  time_t start_time;
 
625
  uint32_t   command;
 
626
  string user;
 
627
  string host;
 
628
  string db;
 
629
  string proc_info;
 
630
  string state_info;
 
631
  string query;
 
632
  thread_info(uint64_t thread_id_arg,
 
633
              time_t start_time_arg,
 
634
              uint32_t command_arg,
 
635
              const string &user_arg,
 
636
              const string &host_arg,
 
637
              const string &db_arg,
 
638
              const string &proc_info_arg,
 
639
              const string &state_info_arg,
 
640
              const string &query_arg)
 
641
    : thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
 
642
      user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
 
643
      state_info(state_info_arg), query(query_arg)
 
644
  {}
 
645
};
 
646
 
 
647
/*****************************************************************************
 
648
  Status functions
 
649
*****************************************************************************/
 
650
 
 
651
static vector<drizzle_show_var *> all_status_vars;
 
652
static vector<drizzle_show_var *> com_status_vars;
 
653
static bool status_vars_inited= 0;
 
654
static int show_var_cmp(const void *var1, const void *var2)
 
655
{
 
656
  return strcmp(((drizzle_show_var*)var1)->name, ((drizzle_show_var*)var2)->name);
 
657
}
 
658
 
 
659
class show_var_cmp_functor
 
660
{
 
661
  public:
 
662
  show_var_cmp_functor() { }
 
663
  inline bool operator()(const drizzle_show_var *var1, const drizzle_show_var *var2) const
 
664
  {
 
665
    int val= strcmp(var1->name, var2->name);
 
666
    return (val < 0);
 
667
  }
 
668
};
 
669
 
 
670
class show_var_remove_if
 
671
{
 
672
  public:
 
673
  show_var_remove_if() { }
 
674
  inline bool operator()(const drizzle_show_var *curr) const
 
675
  {
 
676
    return (curr->type == SHOW_UNDEF);
 
677
  }
 
678
};
 
679
 
 
680
drizzle_show_var *getFrontOfStatusVars()
 
681
{
 
682
  return all_status_vars.front();
 
683
}
 
684
 
 
685
drizzle_show_var *getCommandStatusVars()
 
686
{
 
687
  return com_status_vars.front();
 
688
}
 
689
 
 
690
/*
 
691
  Adds an array of drizzle_show_var entries to the output of SHOW STATUS
 
692
 
 
693
  SYNOPSIS
 
694
    add_status_vars(drizzle_show_var *list)
 
695
    list - an array of drizzle_show_var entries to add to all_status_vars
 
696
           the last entry must be {0,0,SHOW_UNDEF}
 
697
 
 
698
  NOTE
 
699
    The handling of all_status_vars[] is completely internal, it's allocated
 
700
    automatically when something is added to it, and deleted completely when
 
701
    the last entry is removed.
 
702
 
 
703
    As a special optimization, if add_status_vars() is called before
 
704
    init_status_vars(), it assumes "startup mode" - neither concurrent access
 
705
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
 
706
*/
 
707
int add_status_vars(drizzle_show_var *list)
 
708
{
 
709
  int res= 0;
 
710
  if (status_vars_inited)
 
711
    pthread_mutex_lock(&LOCK_status);
 
712
  while (list->name)
 
713
    all_status_vars.insert(all_status_vars.begin(), list++);
 
714
  if (status_vars_inited)
 
715
    sort(all_status_vars.begin(), all_status_vars.end(),
 
716
         show_var_cmp_functor());
 
717
  if (status_vars_inited)
 
718
    pthread_mutex_unlock(&LOCK_status);
 
719
  return res;
 
720
}
 
721
 
 
722
int add_com_status_vars(drizzle_show_var *list)
 
723
{
 
724
  int res= 0;
 
725
 
 
726
  while (list->name)
 
727
    com_status_vars.insert(com_status_vars.begin(), list++);
 
728
  if (status_vars_inited)
 
729
    sort(com_status_vars.begin(), com_status_vars.end(),
 
730
         show_var_cmp_functor());
 
731
 
 
732
  return res;
 
733
}
 
734
 
 
735
/*
 
736
  Make all_status_vars[] usable for SHOW STATUS
 
737
 
 
738
  NOTE
 
739
    See add_status_vars(). Before init_status_vars() call, add_status_vars()
 
740
    works in a special fast "startup" mode. Thus init_status_vars()
 
741
    should be called as late as possible but before enabling multi-threading.
 
742
*/
 
743
void init_status_vars()
 
744
{
 
745
  status_vars_inited= 1;
 
746
  sort(all_status_vars.begin(), all_status_vars.end(),
 
747
       show_var_cmp_functor());
 
748
  sort(com_status_vars.begin(), com_status_vars.end(),
 
749
       show_var_cmp_functor());
 
750
}
 
751
 
 
752
void reset_status_vars()
 
753
{
 
754
  vector<drizzle_show_var *>::iterator p;
 
755
 
 
756
  p= all_status_vars.begin();
 
757
  while (p != all_status_vars.end())
 
758
  {
 
759
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
760
    if ((*p)->type == SHOW_LONG)
 
761
      (*p)->value= 0;
 
762
    ++p;
 
763
  }
 
764
 
 
765
  p= com_status_vars.begin();
 
766
  while (p != com_status_vars.end())
 
767
  {
 
768
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
769
    if ((*p)->type == SHOW_LONG)
 
770
      (*p)->value= 0;
 
771
    ++p;
 
772
  }
 
773
}
 
774
 
 
775
/*
 
776
  catch-all cleanup function, cleans up everything no matter what
 
777
 
 
778
  DESCRIPTION
 
779
    This function is not strictly required if all add_to_status/
 
780
    remove_status_vars are properly paired, but it's a safety measure that
 
781
    deletes everything from the all_status_vars vector even if some
 
782
    remove_status_vars were forgotten
 
783
*/
 
784
void free_status_vars()
 
785
{
 
786
  all_status_vars.clear();
 
787
  com_status_vars.clear();
 
788
}
 
789
 
 
790
/*
 
791
  Removes an array of drizzle_show_var entries from the output of SHOW STATUS
 
792
 
 
793
  SYNOPSIS
 
794
    remove_status_vars(drizzle_show_var *list)
 
795
    list - an array of drizzle_show_var entries to remove to all_status_vars
 
796
           the last entry must be {0,0,SHOW_UNDEF}
 
797
 
 
798
  NOTE
 
799
    there's lots of room for optimizing this, especially in non-sorted mode,
 
800
    but nobody cares - it may be called only in case of failed plugin
 
801
    initialization in the mysqld startup.
 
802
*/
 
803
 
 
804
void remove_status_vars(drizzle_show_var *list)
 
805
{
 
806
  if (status_vars_inited)
 
807
  {
 
808
    pthread_mutex_lock(&LOCK_status);
 
809
    drizzle_show_var *all= all_status_vars.front();
 
810
    int a= 0, b= all_status_vars.size(), c= (a+b)/2;
 
811
 
 
812
    for (; list->name; list++)
 
813
    {
 
814
      int res= 0;
 
815
      for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
 
816
      {
 
817
        res= show_var_cmp(list, all+c);
 
818
        if (res < 0)
 
819
          b= c;
 
820
        else if (res > 0)
 
821
          a= c;
 
822
        else
 
823
          break;
 
824
      }
 
825
      if (res == 0)
 
826
        all[c].type= SHOW_UNDEF;
 
827
    }
 
828
    /* removes all the SHOW_UNDEF elements from the vector */
 
829
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
830
                            all_status_vars.end(),show_var_remove_if()),
 
831
                            all_status_vars.end());
 
832
    pthread_mutex_unlock(&LOCK_status);
 
833
  }
 
834
  else
 
835
  {
 
836
    drizzle_show_var *all= all_status_vars.front();
 
837
    uint32_t i;
 
838
    for (; list->name; list++)
 
839
    {
 
840
      for (i= 0; i < all_status_vars.size(); i++)
 
841
      {
 
842
        if (show_var_cmp(list, all+i))
 
843
          continue;
 
844
        all[i].type= SHOW_UNDEF;
 
845
        break;
 
846
      }
 
847
    }
 
848
    /* removes all the SHOW_UNDEF elements from the vector */
 
849
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
850
                            all_status_vars.end(),show_var_remove_if()),
 
851
                            all_status_vars.end());
 
852
  }
 
853
}
 
854
 
 
855
/* collect status for all running threads */
 
856
 
 
857
void calc_sum_of_all_status(system_status_var *to)
 
858
{
 
859
  /* Ensure that thread id not killed during loop */
 
860
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
861
 
 
862
  /* Get global values as base */
 
863
  *to= global_status_var;
 
864
 
 
865
  /* Add to this status from existing threads */
 
866
  for(SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
867
  {
 
868
    add_to_status(to, &((*it)->status_var));
 
869
  }
 
870
 
 
871
  pthread_mutex_unlock(&LOCK_thread_count);
 
872
  return;
 
873
}
648
874
 
649
875
} /* namespace drizzled */