~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

Merge Stewart.

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
21
20
 
22
21
/* Function with list databases, tables or fields */
23
22
#include "config.h"
24
 
 
25
 
#include "drizzled/data_home.h"
26
 
#include "drizzled/error.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>
 
29
#include <drizzled/data_home.h>
 
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/plugin/info_schema_table.h>
 
45
#include <drizzled/message/schema.pb.h>
 
46
#include <drizzled/plugin/client.h>
 
47
#include <drizzled/cached_directory.h>
 
48
#include "drizzled/sql_table.h"
 
49
#include "drizzled/global_charset_info.h"
 
50
#include "drizzled/pthread_globals.h"
 
51
#include "drizzled/internal/m_string.h"
27
52
#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
 
 
37
53
 
38
54
#include <sys/stat.h>
39
55
 
54
70
  return str ? str : "<nil>";
55
71
}
56
72
 
57
 
int wild_case_compare(const charset_info_st * const cs, const char *str, const char *wildstr)
 
73
static void store_key_options(String *packet, Table *table, KEY *key_info);
 
74
 
 
75
 
 
76
int wild_case_compare(const CHARSET_INFO * const cs, const char *str, const char *wildstr)
58
77
{
59
78
  register int flag;
60
79
 
102
121
  return (*str != '\0');
103
122
}
104
123
 
 
124
 
 
125
/**
 
126
 * @brief
 
127
 *   Find subdirectories (schemas) in a given directory (datadir).
 
128
 *
 
129
 * @param[in]  session    Thread Cursor
 
130
 * @param[out] files      Put found entries in this list
 
131
 * @param[in]  path       Path to database
 
132
 * @param[in]  wild       Filter for found entries
 
133
 *
 
134
 * @retval false   Success
 
135
 * @retval true    Error
 
136
 */
 
137
static bool find_schemas(Session *session, vector<LEX_STRING*> &files,
 
138
                         const char *path, const char *wild)
 
139
{
 
140
  if (wild && (wild[0] == '\0'))
 
141
    wild= 0;
 
142
 
 
143
  CachedDirectory directory(path);
 
144
 
 
145
  if (directory.fail())
 
146
  {
 
147
    errno= directory.getError();
 
148
    my_error(ER_CANT_READ_DIR, MYF(0), path, errno);
 
149
 
 
150
    return true;
 
151
  }
 
152
 
 
153
  CachedDirectory::Entries entries= directory.getEntries();
 
154
  CachedDirectory::Entries::iterator entry_iter= entries.begin();
 
155
 
 
156
  while (entry_iter != entries.end())
 
157
  {
 
158
    uint32_t file_name_len;
 
159
    char uname[NAME_LEN + 1];                   /* Unencoded name */
 
160
    struct stat entry_stat;
 
161
    CachedDirectory::Entry *entry= *entry_iter;
 
162
 
 
163
    if ((entry->filename == ".") || (entry->filename == ".."))
 
164
    {
 
165
      ++entry_iter;
 
166
      continue;
 
167
    }
 
168
 
 
169
    if (stat(entry->filename.c_str(), &entry_stat))
 
170
    {
 
171
      errno= errno;
 
172
      my_error(ER_CANT_GET_STAT, MYF(0), entry->filename.c_str(), errno);
 
173
      return(true);
 
174
    }
 
175
 
 
176
    if (! S_ISDIR(entry_stat.st_mode))
 
177
    {
 
178
      ++entry_iter;
 
179
      continue;
 
180
    }
 
181
 
 
182
    file_name_len= filename_to_tablename(entry->filename.c_str(), uname,
 
183
                                         sizeof(uname));
 
184
    if (wild && internal::wild_compare(uname, wild, 0))
 
185
    {
 
186
      ++entry_iter;
 
187
      continue;
 
188
    }
 
189
 
 
190
    LEX_STRING *file_name= 0;
 
191
    file_name= session->make_lex_string(file_name, uname, file_name_len, true);
 
192
    if (file_name == NULL)
 
193
      return(true);
 
194
 
 
195
    files.push_back(file_name);
 
196
    ++entry_iter;
 
197
  }
 
198
 
 
199
  return false;
 
200
}
 
201
 
 
202
 
 
203
bool drizzled_show_create(Session *session, TableList *table_list, bool is_if_not_exists)
 
204
{
 
205
  char buff[2048];
 
206
  String buffer(buff, sizeof(buff), system_charset_info);
 
207
 
 
208
  /* Only one table for now, but VIEW can involve several tables */
 
209
  if (session->openTables(table_list))
 
210
  {
 
211
    if (session->is_error())
 
212
      return true;
 
213
 
 
214
    /*
 
215
      Clear all messages with 'error' level status and
 
216
      issue a warning with 'warning' level status in
 
217
      case of invalid view and last error is ER_VIEW_INVALID
 
218
    */
 
219
    drizzle_reset_errors(session, true);
 
220
    session->clear_error();
 
221
  }
 
222
 
 
223
  buffer.length(0);
 
224
 
 
225
  if (store_create_info(table_list, &buffer, is_if_not_exists))
 
226
    return true;
 
227
 
 
228
  List<Item> field_list;
 
229
  {
 
230
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
 
231
    // 1024 is for not to confuse old clients
 
232
    field_list.push_back(new Item_empty_string("Create Table",
 
233
                                               max(buffer.length(),(uint32_t)1024)));
 
234
  }
 
235
 
 
236
  if (session->client->sendFields(&field_list))
 
237
    return true;
 
238
  {
 
239
    session->client->store(table_list->table->alias);
 
240
  }
 
241
 
 
242
  session->client->store(buffer.ptr(), buffer.length());
 
243
 
 
244
  if (session->client->flush())
 
245
    return true;
 
246
 
 
247
  session->my_eof();
 
248
  return false;
 
249
}
 
250
 
 
251
/**
 
252
  Get a CREATE statement for a given database.
 
253
 
 
254
  The database is identified by its name, passed as @c dbname parameter.
 
255
  The name should be encoded using the system character set (UTF8 currently).
 
256
 
 
257
  Resulting statement is stored in the string pointed by @c buffer. The string
 
258
  is emptied first and its character set is set to the system character set.
 
259
 
 
260
  If is_if_not_exists is set, then
 
261
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
 
262
  in @c create_options are ignored.
 
263
 
 
264
  @param  session           The current thread instance.
 
265
  @param  dbname        The name of the database.
 
266
  @param  buffer        A String instance where the statement is stored.
 
267
  @param  create_info   If not NULL, the options member influences the resulting
 
268
                        CRATE statement.
 
269
 
 
270
  @returns true if errors are detected, false otherwise.
 
271
*/
 
272
 
 
273
static bool store_db_create_info(const char *dbname, String *buffer, bool if_not_exists)
 
274
{
 
275
  message::Schema schema;
 
276
 
 
277
  if (not my_strcasecmp(system_charset_info, dbname,
 
278
                        INFORMATION_SCHEMA_NAME.c_str()))
 
279
  {
 
280
    dbname= INFORMATION_SCHEMA_NAME.c_str();
 
281
  }
 
282
  else if (not my_strcasecmp(system_charset_info, dbname,
 
283
                             "data_dictionary"))
 
284
  {
 
285
    dbname= "data_dictionary";
 
286
  }
 
287
  else
 
288
  {
 
289
    int r= get_database_metadata(dbname, schema);
 
290
    if (r < 0)
 
291
      return true;
 
292
  }
 
293
 
 
294
  buffer->length(0);
 
295
  buffer->free();
 
296
  buffer->set_charset(system_charset_info);
 
297
  buffer->append(STRING_WITH_LEN("CREATE DATABASE "));
 
298
 
 
299
  if (if_not_exists)
 
300
    buffer->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
301
 
 
302
  buffer->append_identifier(dbname, strlen(dbname));
 
303
 
 
304
  if (schema.has_collation() && strcmp(schema.collation().c_str(),
 
305
                                       default_charset_info->name))
 
306
  {
 
307
    buffer->append(" COLLATE = ");
 
308
    buffer->append(schema.collation().c_str());
 
309
  }
 
310
 
 
311
  return false;
 
312
}
 
313
 
 
314
bool mysqld_show_create_db(Session *session, char *dbname, bool if_not_exists)
 
315
{
 
316
  char buff[2048];
 
317
  String buffer(buff, sizeof(buff), system_charset_info);
 
318
 
 
319
  if (store_db_create_info(dbname, &buffer, if_not_exists))
 
320
  {
 
321
    /*
 
322
      This assumes that the only reason for which store_db_create_info()
 
323
      can fail is incorrect database name (which is the case now).
 
324
    */
 
325
    my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
 
326
    return true;
 
327
  }
 
328
 
 
329
  List<Item> field_list;
 
330
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
 
331
  field_list.push_back(new Item_empty_string("Create Database",1024));
 
332
 
 
333
  if (session->client->sendFields(&field_list))
 
334
    return true;
 
335
 
 
336
  session->client->store(dbname, strlen(dbname));
 
337
  session->client->store(buffer.ptr(), buffer.length());
 
338
 
 
339
  if (session->client->flush())
 
340
    return true;
 
341
  session->my_eof();
 
342
  return false;
 
343
}
 
344
 
105
345
/*
106
346
  Get the quote character for displaying an identifier.
107
347
 
127
367
  return '`';
128
368
}
129
369
 
130
 
namespace show {
131
 
 
132
 
bool buildScemas(Session *session)
133
 
{
134
 
  session->getLex()->sql_command= SQLCOM_SELECT;
135
 
  session->getLex()->statement= new statement::Show(session);
136
 
 
137
 
  std::string column_name= "Database";
138
 
  if (session->getLex()->wild)
139
 
  {
140
 
    column_name.append(" (");
141
 
    column_name.append(session->getLex()->wild->ptr());
142
 
    column_name.append(")");
143
 
  }
144
 
 
145
 
  if (session->getLex()->current_select->where)
146
 
  {
147
 
    if (prepare_new_schema_table(session, session->getLex(), "SCHEMAS"))
148
 
      return false;
149
 
  }
150
 
  else
151
 
  {
152
 
    if (prepare_new_schema_table(session, session->getLex(), "SHOW_SCHEMAS"))
153
 
      return false;
154
 
  }
155
 
 
156
 
  Item_field *my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "SCHEMA_NAME");
157
 
  my_field->is_autogenerated_name= false;
158
 
  my_field->set_name(column_name.c_str(), column_name.length(), system_charset_info);
159
 
 
160
 
  if (session->add_item_to_list(my_field))
161
 
    return false;
162
 
 
163
 
  if (session->add_order_to_list(my_field, true))
164
 
    return false;
165
 
 
166
 
  return true;
167
 
}
168
 
 
169
 
bool buildTables(Session *session, const char *ident)
170
 
{
171
 
  session->getLex()->sql_command= SQLCOM_SELECT;
172
 
 
173
 
  drizzled::statement::Show *select= new statement::Show(session);
174
 
  session->getLex()->statement= select;
175
 
 
176
 
  std::string column_name= "Tables_in_";
177
 
 
178
 
  util::string::const_shared_ptr schema(session->schema());
179
 
  if (ident)
180
 
  {
181
 
    identifier::Schema identifier(ident);
182
 
    column_name.append(ident);
183
 
    session->getLex()->select_lex.db= const_cast<char *>(ident);
184
 
    if (not plugin::StorageEngine::doesSchemaExist(identifier))
185
 
    {
186
 
      my_error(ER_BAD_DB_ERROR, MYF(0), ident);
187
 
    }
188
 
    select->setShowPredicate(ident, "");
189
 
  }
190
 
  else if (schema and not schema->empty())
191
 
  {
192
 
    column_name.append(*schema);
193
 
    select->setShowPredicate(*schema, "");
194
 
  }
195
 
  else
196
 
  {
197
 
    my_error(ER_NO_DB_ERROR, MYF(0));
198
 
    return false;
199
 
  }
200
 
 
201
 
 
202
 
  if (session->getLex()->wild)
203
 
  {
204
 
    column_name.append(" (");
205
 
    column_name.append(session->getLex()->wild->ptr());
206
 
    column_name.append(")");
207
 
  }
208
 
 
209
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_TABLES"))
210
 
    return false;
211
 
 
212
 
  Item_field *my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "TABLE_NAME");
213
 
  my_field->is_autogenerated_name= false;
214
 
  my_field->set_name(column_name.c_str(), column_name.length(), system_charset_info);
215
 
 
216
 
  if (session->add_item_to_list(my_field))
217
 
    return false;
218
 
 
219
 
  if (session->add_order_to_list(my_field, true))
220
 
    return false;
221
 
 
222
 
  return true;
223
 
}
224
 
 
225
 
bool buildTemporaryTables(Session *session)
226
 
{
227
 
  session->getLex()->sql_command= SQLCOM_SELECT;
228
 
 
229
 
  session->getLex()->statement= new statement::Show(session);
230
 
 
231
 
 
232
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_TEMPORARY_TABLES"))
233
 
    return false;
234
 
 
235
 
  if (session->add_item_to_list( new Item_field(&session->lex->current_select->context, NULL, NULL, "*")))
236
 
    return false;
237
 
 
238
 
  (session->lex->current_select->with_wild)++;
239
 
 
240
 
  return true;
241
 
}
242
 
 
243
 
bool buildTableStatus(Session *session, const char *ident)
244
 
{
245
 
  session->getLex()->sql_command= SQLCOM_SELECT;
246
 
  drizzled::statement::Show *select= new statement::Show(session);
247
 
  session->getLex()->statement= select;
248
 
 
249
 
  std::string column_name= "Tables_in_";
250
 
 
251
 
  util::string::const_shared_ptr schema(session->schema());
252
 
  if (ident)
253
 
  {
254
 
    session->getLex()->select_lex.db= const_cast<char *>(ident);
255
 
 
256
 
    identifier::Schema identifier(ident);
257
 
    if (not plugin::StorageEngine::doesSchemaExist(identifier))
258
 
    {
259
 
      my_error(ER_BAD_DB_ERROR, MYF(0), ident);
260
 
    }
261
 
 
262
 
    select->setShowPredicate(ident, "");
263
 
  }
264
 
  else if (schema)
265
 
  {
266
 
    select->setShowPredicate(*schema, "");
267
 
  }
268
 
  else
269
 
  {
270
 
    my_error(ER_NO_DB_ERROR, MYF(0));
271
 
    return false;
272
 
  }
273
 
 
274
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_TABLE_STATUS"))
275
 
    return false;
276
 
 
277
 
  if (session->add_item_to_list( new Item_field(&session->lex->current_select->
278
 
                                                  context,
279
 
                                                  NULL, NULL, "*")))
280
 
    return false;
281
 
 
282
 
  (session->lex->current_select->with_wild)++;
283
 
 
284
 
  return true;
285
 
}
286
 
 
287
 
bool buildEngineStatus(Session *session, LEX_STRING)
288
 
{
289
 
  session->getLex()->sql_command= SQLCOM_SELECT;
290
 
  drizzled::statement::Show *select= new statement::Show(session);
291
 
  session->getLex()->statement= select;
292
 
 
293
 
  my_error(ER_USE_DATA_DICTIONARY);
 
370
 
 
371
#define LIST_PROCESS_HOST_LEN 64
 
372
 
 
373
static bool get_field_default_value(Field *timestamp_field,
 
374
                                    Field *field, String *def_value,
 
375
                                    bool quoted)
 
376
{
 
377
  bool has_default;
 
378
  bool has_now_default;
 
379
 
 
380
  /*
 
381
     We are using CURRENT_TIMESTAMP instead of NOW because it is
 
382
     more standard
 
383
  */
 
384
  has_now_default= (timestamp_field == field &&
 
385
                    field->unireg_check != Field::TIMESTAMP_UN_FIELD);
 
386
 
 
387
  has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
 
388
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
 
389
                field->unireg_check != Field::NEXT_NUMBER);
 
390
 
 
391
  def_value->length(0);
 
392
  if (has_default)
 
393
  {
 
394
    if (has_now_default)
 
395
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
 
396
    else if (!field->is_null())
 
397
    {                                             // Not null by default
 
398
      char tmp[MAX_FIELD_WIDTH];
 
399
      String type(tmp, sizeof(tmp), field->charset());
 
400
      field->val_str(&type);
 
401
      if (type.length())
 
402
      {
 
403
        String def_val;
 
404
        uint32_t dummy_errors;
 
405
        /* convert to system_charset_info == utf8 */
 
406
        def_val.copy(type.ptr(), type.length(), field->charset(),
 
407
                     system_charset_info, &dummy_errors);
 
408
        if (quoted)
 
409
          append_unescaped(def_value, def_val.ptr(), def_val.length());
 
410
        else
 
411
          def_value->append(def_val.ptr(), def_val.length());
 
412
      }
 
413
      else if (quoted)
 
414
        def_value->append(STRING_WITH_LEN("''"));
 
415
    }
 
416
    else if (field->maybe_null() && quoted)
 
417
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
 
418
    else
 
419
      return false;
 
420
  }
 
421
  return has_default;
 
422
}
 
423
 
 
424
/*
 
425
  Build a CREATE TABLE statement for a table.
 
426
 
 
427
  SYNOPSIS
 
428
    store_create_info()
 
429
    table_list        A list containing one table to write statement
 
430
                      for.
 
431
    packet            Pointer to a string where statement will be
 
432
                      written.
 
433
 
 
434
  NOTE
 
435
    Currently always return 0, but might return error code in the
 
436
    future.
 
437
 
 
438
  RETURN
 
439
    0       OK
 
440
 */
 
441
 
 
442
int store_create_info(TableList *table_list, String *packet, bool is_if_not_exists)
 
443
{
 
444
  List<Item> field_list;
 
445
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
 
446
  const char *alias;
 
447
  string buff;
 
448
  String type(tmp, sizeof(tmp), system_charset_info);
 
449
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
 
450
  Field **ptr,*field;
 
451
  uint32_t primary_key;
 
452
  KEY *key_info;
 
453
  Table *table= table_list->table;
 
454
  Cursor *cursor= table->cursor;
 
455
  TableShare *share= table->s;
 
456
  HA_CREATE_INFO create_info;
 
457
  bool show_table_options= false;
 
458
  my_bitmap_map *old_map;
 
459
 
 
460
  table->restoreRecordAsDefault(); // Get empty record
 
461
 
 
462
  if (share->tmp_table)
 
463
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
 
464
  else
 
465
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
 
466
  if (is_if_not_exists)
 
467
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
468
  alias= share->table_name.str;
 
469
 
 
470
  packet->append_identifier(alias, strlen(alias));
 
471
  packet->append(STRING_WITH_LEN(" (\n"));
 
472
  /*
 
473
    We need this to get default values from the table
 
474
    We have to restore the read_set if we are called from insert in case
 
475
    of row based replication.
 
476
  */
 
477
  old_map= table->use_all_columns(table->read_set);
 
478
 
 
479
  for (ptr=table->field ; (field= *ptr); ptr++)
 
480
  {
 
481
    uint32_t flags = field->flags;
 
482
 
 
483
    if (ptr != table->field)
 
484
      packet->append(STRING_WITH_LEN(",\n"));
 
485
 
 
486
    packet->append(STRING_WITH_LEN("  "));
 
487
    packet->append_identifier(field->field_name, strlen(field->field_name));
 
488
    packet->append(' ');
 
489
    // check for surprises from the previous call to Field::sql_type()
 
490
    if (type.ptr() != tmp)
 
491
      type.set(tmp, sizeof(tmp), system_charset_info);
 
492
    else
 
493
      type.set_charset(system_charset_info);
 
494
 
 
495
    field->sql_type(type);
 
496
    packet->append(type.ptr(), type.length(), system_charset_info);
 
497
 
 
498
    if (field->has_charset())
 
499
    {
 
500
      if (field->charset() != share->table_charset)
 
501
      {
 
502
        packet->append(STRING_WITH_LEN(" CHARACTER SET "));
 
503
        packet->append(field->charset()->csname);
 
504
      }
 
505
 
 
506
      /*
 
507
        For string types dump collation name only if
 
508
        collation is not primary for the given charset
 
509
      */
 
510
      if (!(field->charset()->state & MY_CS_PRIMARY))
 
511
      {
 
512
        packet->append(STRING_WITH_LEN(" COLLATE "));
 
513
        packet->append(field->charset()->name);
 
514
      }
 
515
    }
 
516
 
 
517
    if (flags & NOT_NULL_FLAG)
 
518
      packet->append(STRING_WITH_LEN(" NOT NULL"));
 
519
    else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
520
    {
 
521
      /*
 
522
        TIMESTAMP field require explicit NULL flag, because unlike
 
523
        all other fields they are treated as NOT NULL by default.
 
524
      */
 
525
      packet->append(STRING_WITH_LEN(" NULL"));
 
526
    }
 
527
    {
 
528
      /*
 
529
        Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
 
530
        and about STORAGE (DISK or MEMORY).
 
531
      */
 
532
      enum column_format_type column_format= (enum column_format_type)
 
533
        ((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
534
      if (column_format)
 
535
      {
 
536
        packet->append(STRING_WITH_LEN(" /*!"));
 
537
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
 
538
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
 
539
          packet->append(STRING_WITH_LEN(" FIXED */"));
 
540
        else
 
541
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
 
542
      }
 
543
    }
 
544
    if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
 
545
    {
 
546
      packet->append(STRING_WITH_LEN(" DEFAULT "));
 
547
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
 
548
    }
 
549
 
 
550
    if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
551
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
 
552
 
 
553
    if (field->unireg_check == Field::NEXT_NUMBER)
 
554
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
 
555
 
 
556
    if (field->comment.length)
 
557
    {
 
558
      packet->append(STRING_WITH_LEN(" COMMENT "));
 
559
      append_unescaped(packet, field->comment.str, field->comment.length);
 
560
    }
 
561
  }
 
562
 
 
563
  key_info= table->key_info;
 
564
  memset(&create_info, 0, sizeof(create_info));
 
565
  /* Allow update_create_info to update row type */
 
566
  create_info.row_type= share->row_type;
 
567
  cursor->update_create_info(&create_info);
 
568
  primary_key= share->primary_key;
 
569
 
 
570
  for (uint32_t i=0 ; i < share->keys ; i++,key_info++)
 
571
  {
 
572
    KEY_PART_INFO *key_part= key_info->key_part;
 
573
    bool found_primary=0;
 
574
    packet->append(STRING_WITH_LEN(",\n  "));
 
575
 
 
576
    if (i == primary_key && is_primary_key(key_info))
 
577
    {
 
578
      found_primary=1;
 
579
      /*
 
580
        No space at end, because a space will be added after where the
 
581
        identifier would go, but that is not added for primary key.
 
582
      */
 
583
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
 
584
    }
 
585
    else if (key_info->flags & HA_NOSAME)
 
586
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
 
587
    else
 
588
      packet->append(STRING_WITH_LEN("KEY "));
 
589
 
 
590
    if (!found_primary)
 
591
     packet->append_identifier(key_info->name, strlen(key_info->name));
 
592
 
 
593
    packet->append(STRING_WITH_LEN(" ("));
 
594
 
 
595
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
596
    {
 
597
      if (j)
 
598
        packet->append(',');
 
599
 
 
600
      if (key_part->field)
 
601
        packet->append_identifier(key_part->field->field_name,
 
602
                                  strlen(key_part->field->field_name));
 
603
      if (key_part->field &&
 
604
          (key_part->length !=
 
605
           table->field[key_part->fieldnr-1]->key_length()))
 
606
      {
 
607
        buff.assign("(");
 
608
        buff.append(to_string((int32_t) key_part->length /
 
609
                              key_part->field->charset()->mbmaxlen));
 
610
        buff.append(")");
 
611
        packet->append(buff.c_str(), buff.length());
 
612
      }
 
613
    }
 
614
    packet->append(')');
 
615
    store_key_options(packet, table, key_info);
 
616
  }
 
617
 
 
618
  /*
 
619
    Get possible foreign key definitions stored in InnoDB and append them
 
620
    to the CREATE TABLE statement
 
621
  */
 
622
 
 
623
  if ((for_str= cursor->get_foreign_key_create_info()))
 
624
  {
 
625
    packet->append(for_str, strlen(for_str));
 
626
    cursor->free_foreign_key_create_info(for_str);
 
627
  }
 
628
 
 
629
  packet->append(STRING_WITH_LEN("\n)"));
 
630
  {
 
631
    show_table_options= true;
 
632
    /*
 
633
      Get possible table space definitions and append them
 
634
      to the CREATE TABLE statement
 
635
    */
 
636
 
 
637
    /* 
 
638
      We should always store engine since we will now be 
 
639
      making sure engines accept options (aka... no
 
640
      dangling arguments for engines.
 
641
    */
 
642
    packet->append(STRING_WITH_LEN(" ENGINE="));
 
643
    packet->append(cursor->engine->getName().c_str());
 
644
 
 
645
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
 
646
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
 
647
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
 
648
      packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
 
649
    if (create_info.row_type != ROW_TYPE_DEFAULT)
 
650
    {
 
651
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
 
652
      packet->append(ha_row_type[(uint32_t) create_info.row_type]);
 
653
    }
 
654
    if (table->s->hasKeyBlockSize())
 
655
    {
 
656
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
657
      buff= to_string(table->s->getKeyBlockSize());
 
658
      packet->append(buff.c_str(), buff.length());
 
659
    }
 
660
    if (share->block_size)
 
661
    {
 
662
      packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
 
663
      buff= to_string(share->block_size);
 
664
      packet->append(buff.c_str(), buff.length());
 
665
    }
 
666
    table->cursor->append_create_info(packet);
 
667
    if (share->hasComment() && share->getCommentLength())
 
668
    {
 
669
      packet->append(STRING_WITH_LEN(" COMMENT="));
 
670
      append_unescaped(packet, share->getComment(),
 
671
                       share->getCommentLength());
 
672
    }
 
673
  }
 
674
  table->restore_column_map(old_map);
 
675
  return(0);
 
676
}
 
677
 
 
678
static void store_key_options(String *packet, Table *table, KEY *key_info)
 
679
{
 
680
  char *end, buff[32];
 
681
 
 
682
  if (key_info->algorithm == HA_KEY_ALG_BTREE)
 
683
    packet->append(STRING_WITH_LEN(" USING BTREE"));
 
684
 
 
685
  if (key_info->algorithm == HA_KEY_ALG_HASH)
 
686
    packet->append(STRING_WITH_LEN(" USING HASH"));
 
687
 
 
688
  if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
 
689
      table->s->getKeyBlockSize() != key_info->block_size)
 
690
  {
 
691
    packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
692
    end= internal::int64_t10_to_str(key_info->block_size, buff, 10);
 
693
    packet->append(buff, (uint32_t) (end - buff));
 
694
  }
 
695
 
 
696
  assert(test(key_info->flags & HA_USES_COMMENT) ==
 
697
              (key_info->comment.length > 0));
 
698
  if (key_info->flags & HA_USES_COMMENT)
 
699
  {
 
700
    packet->append(STRING_WITH_LEN(" COMMENT "));
 
701
    append_unescaped(packet, key_info->comment.str,
 
702
                     key_info->comment.length);
 
703
  }
 
704
}
 
705
 
 
706
 
 
707
/****************************************************************************
 
708
  Return info about all processes
 
709
  returns for each thread: thread id, user, host, db, command, info
 
710
****************************************************************************/
 
711
 
 
712
class thread_info
 
713
{
 
714
  thread_info();
 
715
public:
 
716
  uint64_t thread_id;
 
717
  time_t start_time;
 
718
  uint32_t   command;
 
719
  string user;
 
720
  string host;
 
721
  string db;
 
722
  string proc_info;
 
723
  string state_info;
 
724
  string query;
 
725
  thread_info(uint64_t thread_id_arg,
 
726
              time_t start_time_arg,
 
727
              uint32_t command_arg,
 
728
              const string &user_arg,
 
729
              const string &host_arg,
 
730
              const string &db_arg,
 
731
              const string &proc_info_arg,
 
732
              const string &state_info_arg,
 
733
              const string &query_arg)
 
734
    : thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
 
735
      user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
 
736
      state_info(state_info_arg), query(query_arg)
 
737
  {}
 
738
};
 
739
 
 
740
/*****************************************************************************
 
741
  Status functions
 
742
*****************************************************************************/
 
743
 
 
744
static vector<drizzle_show_var *> all_status_vars;
 
745
static vector<drizzle_show_var *> com_status_vars;
 
746
static bool status_vars_inited= 0;
 
747
static int show_var_cmp(const void *var1, const void *var2)
 
748
{
 
749
  return strcmp(((drizzle_show_var*)var1)->name, ((drizzle_show_var*)var2)->name);
 
750
}
 
751
 
 
752
class show_var_cmp_functor
 
753
{
 
754
  public:
 
755
  show_var_cmp_functor() { }
 
756
  inline bool operator()(const drizzle_show_var *var1, const drizzle_show_var *var2) const
 
757
  {
 
758
    int val= strcmp(var1->name, var2->name);
 
759
    return (val < 0);
 
760
  }
 
761
};
 
762
 
 
763
class show_var_remove_if
 
764
{
 
765
  public:
 
766
  show_var_remove_if() { }
 
767
  inline bool operator()(const drizzle_show_var *curr) const
 
768
  {
 
769
    return (curr->type == SHOW_UNDEF);
 
770
  }
 
771
};
 
772
 
 
773
drizzle_show_var *getFrontOfStatusVars()
 
774
{
 
775
  return all_status_vars.front();
 
776
}
 
777
 
 
778
drizzle_show_var *getCommandStatusVars()
 
779
{
 
780
  return com_status_vars.front();
 
781
}
 
782
 
 
783
/*
 
784
  Adds an array of drizzle_show_var entries to the output of SHOW STATUS
 
785
 
 
786
  SYNOPSIS
 
787
    add_status_vars(drizzle_show_var *list)
 
788
    list - an array of drizzle_show_var entries to add to all_status_vars
 
789
           the last entry must be {0,0,SHOW_UNDEF}
 
790
 
 
791
  NOTE
 
792
    The handling of all_status_vars[] is completely internal, it's allocated
 
793
    automatically when something is added to it, and deleted completely when
 
794
    the last entry is removed.
 
795
 
 
796
    As a special optimization, if add_status_vars() is called before
 
797
    init_status_vars(), it assumes "startup mode" - neither concurrent access
 
798
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
 
799
*/
 
800
int add_status_vars(drizzle_show_var *list)
 
801
{
 
802
  int res= 0;
 
803
  if (status_vars_inited)
 
804
    pthread_mutex_lock(&LOCK_status);
 
805
  while (list->name)
 
806
    all_status_vars.insert(all_status_vars.begin(), list++);
 
807
  if (status_vars_inited)
 
808
    sort(all_status_vars.begin(), all_status_vars.end(),
 
809
         show_var_cmp_functor());
 
810
  if (status_vars_inited)
 
811
    pthread_mutex_unlock(&LOCK_status);
 
812
  return res;
 
813
}
 
814
 
 
815
int add_com_status_vars(drizzle_show_var *list)
 
816
{
 
817
  int res= 0;
 
818
 
 
819
  while (list->name)
 
820
    com_status_vars.insert(com_status_vars.begin(), list++);
 
821
  if (status_vars_inited)
 
822
    sort(com_status_vars.begin(), com_status_vars.end(),
 
823
         show_var_cmp_functor());
 
824
 
 
825
  return res;
 
826
}
 
827
 
 
828
/*
 
829
  Make all_status_vars[] usable for SHOW STATUS
 
830
 
 
831
  NOTE
 
832
    See add_status_vars(). Before init_status_vars() call, add_status_vars()
 
833
    works in a special fast "startup" mode. Thus init_status_vars()
 
834
    should be called as late as possible but before enabling multi-threading.
 
835
*/
 
836
void init_status_vars()
 
837
{
 
838
  status_vars_inited= 1;
 
839
  sort(all_status_vars.begin(), all_status_vars.end(),
 
840
       show_var_cmp_functor());
 
841
  sort(com_status_vars.begin(), com_status_vars.end(),
 
842
       show_var_cmp_functor());
 
843
}
 
844
 
 
845
void reset_status_vars()
 
846
{
 
847
  vector<drizzle_show_var *>::iterator p;
 
848
 
 
849
  p= all_status_vars.begin();
 
850
  while (p != all_status_vars.end())
 
851
  {
 
852
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
853
    if ((*p)->type == SHOW_LONG)
 
854
      (*p)->value= 0;
 
855
    ++p;
 
856
  }
 
857
 
 
858
  p= com_status_vars.begin();
 
859
  while (p != com_status_vars.end())
 
860
  {
 
861
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
862
    if ((*p)->type == SHOW_LONG)
 
863
      (*p)->value= 0;
 
864
    ++p;
 
865
  }
 
866
}
 
867
 
 
868
/*
 
869
  catch-all cleanup function, cleans up everything no matter what
 
870
 
 
871
  DESCRIPTION
 
872
    This function is not strictly required if all add_to_status/
 
873
    remove_status_vars are properly paired, but it's a safety measure that
 
874
    deletes everything from the all_status_vars vector even if some
 
875
    remove_status_vars were forgotten
 
876
*/
 
877
void free_status_vars()
 
878
{
 
879
  all_status_vars.clear();
 
880
  com_status_vars.clear();
 
881
}
 
882
 
 
883
/*
 
884
  Removes an array of drizzle_show_var entries from the output of SHOW STATUS
 
885
 
 
886
  SYNOPSIS
 
887
    remove_status_vars(drizzle_show_var *list)
 
888
    list - an array of drizzle_show_var entries to remove to all_status_vars
 
889
           the last entry must be {0,0,SHOW_UNDEF}
 
890
 
 
891
  NOTE
 
892
    there's lots of room for optimizing this, especially in non-sorted mode,
 
893
    but nobody cares - it may be called only in case of failed plugin
 
894
    initialization in the mysqld startup.
 
895
*/
 
896
 
 
897
void remove_status_vars(drizzle_show_var *list)
 
898
{
 
899
  if (status_vars_inited)
 
900
  {
 
901
    pthread_mutex_lock(&LOCK_status);
 
902
    drizzle_show_var *all= all_status_vars.front();
 
903
    int a= 0, b= all_status_vars.size(), c= (a+b)/2;
 
904
 
 
905
    for (; list->name; list++)
 
906
    {
 
907
      int res= 0;
 
908
      for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
 
909
      {
 
910
        res= show_var_cmp(list, all+c);
 
911
        if (res < 0)
 
912
          b= c;
 
913
        else if (res > 0)
 
914
          a= c;
 
915
        else
 
916
          break;
 
917
      }
 
918
      if (res == 0)
 
919
        all[c].type= SHOW_UNDEF;
 
920
    }
 
921
    /* removes all the SHOW_UNDEF elements from the vector */
 
922
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
923
                            all_status_vars.end(),show_var_remove_if()),
 
924
                            all_status_vars.end());
 
925
    pthread_mutex_unlock(&LOCK_status);
 
926
  }
 
927
  else
 
928
  {
 
929
    drizzle_show_var *all= all_status_vars.front();
 
930
    uint32_t i;
 
931
    for (; list->name; list++)
 
932
    {
 
933
      for (i= 0; i < all_status_vars.size(); i++)
 
934
      {
 
935
        if (show_var_cmp(list, all+i))
 
936
          continue;
 
937
        all[i].type= SHOW_UNDEF;
 
938
        break;
 
939
      }
 
940
    }
 
941
    /* removes all the SHOW_UNDEF elements from the vector */
 
942
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
943
                            all_status_vars.end(),show_var_remove_if()),
 
944
                            all_status_vars.end());
 
945
  }
 
946
}
 
947
 
 
948
/* collect status for all running threads */
 
949
 
 
950
void calc_sum_of_all_status(system_status_var *to)
 
951
{
 
952
  /* Ensure that thread id not killed during loop */
 
953
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
954
 
 
955
  /* Get global values as base */
 
956
  *to= global_status_var;
 
957
 
 
958
  /* Add to this status from existing threads */
 
959
  for(vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
960
  {
 
961
    add_to_status(to, &((*it)->status_var));
 
962
  }
 
963
 
 
964
  pthread_mutex_unlock(&LOCK_thread_count);
 
965
  return;
 
966
}
 
967
 
 
968
 
 
969
static int make_table_list(Session *session, Select_Lex *sel,
 
970
                           LEX_STRING *db_name, LEX_STRING *table_name)
 
971
{
 
972
  Table_ident *table_ident;
 
973
  table_ident= new Table_ident(*db_name, *table_name);
 
974
  sel->init_query();
 
975
  if (! sel->add_table_to_list(session, table_ident, 0, 0, TL_READ))
 
976
    return 1;
 
977
  return 0;
 
978
}
 
979
 
 
980
 
 
981
/**
 
982
  @brief    Get lookup value from the part of 'WHERE' condition
 
983
 
 
984
  @details This function gets lookup value from
 
985
           the part of 'WHERE' condition if it's possible and
 
986
           fill appropriate lookup_field_vals struct field
 
987
           with this value.
 
988
 
 
989
  @param[in]      session                   thread Cursor
 
990
  @param[in]      item_func             part of WHERE condition
 
991
  @param[in]      table                 I_S table
 
992
  @param[in, out] lookup_field_vals     Struct which holds lookup values
 
993
 
 
994
  @return
 
995
    0             success
 
996
    1             error, there can be no matching records for the condition
 
997
*/
 
998
 
 
999
static bool get_lookup_value(Session *session, Item_func *item_func,
 
1000
                             TableList *table,
 
1001
                             LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1002
                             plugin::InfoSchemaTable *schema_table)
 
1003
{
 
1004
  const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1005
    schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1006
  const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1007
    schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
 
1008
 
 
1009
  if (item_func->functype() == Item_func::EQ_FUNC ||
 
1010
      item_func->functype() == Item_func::EQUAL_FUNC)
 
1011
  {
 
1012
    int idx_field, idx_val;
 
1013
    char tmp[MAX_FIELD_WIDTH];
 
1014
    String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
 
1015
    Item_field *item_field;
 
1016
    const CHARSET_INFO * const cs= system_charset_info;
 
1017
 
 
1018
    if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
 
1019
        item_func->arguments()[1]->const_item())
 
1020
    {
 
1021
      idx_field= 0;
 
1022
      idx_val= 1;
 
1023
    }
 
1024
    else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
 
1025
             item_func->arguments()[0]->const_item())
 
1026
    {
 
1027
      idx_field= 1;
 
1028
      idx_val= 0;
 
1029
    }
 
1030
    else
 
1031
      return 0;
 
1032
 
 
1033
    item_field= (Item_field*) item_func->arguments()[idx_field];
 
1034
    if (table->table != item_field->field->table)
 
1035
      return 0;
 
1036
    tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
 
1037
 
 
1038
    /* impossible value */
 
1039
    if (!tmp_str)
 
1040
      return 1;
 
1041
 
 
1042
    /* Lookup value is database name */
 
1043
    if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
 
1044
                               (unsigned char *) item_field->field_name,
 
1045
                               strlen(item_field->field_name), 0))
 
1046
    {
 
1047
      session->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
 
1048
                           tmp_str->length(), false);
 
1049
    }
 
1050
    /* Lookup value is table name */
 
1051
    else if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name2,
 
1052
                                    strlen(field_name2),
 
1053
                                    (unsigned char *) item_field->field_name,
 
1054
                                    strlen(item_field->field_name), 0))
 
1055
    {
 
1056
      session->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
 
1057
                           tmp_str->length(), false);
 
1058
    }
 
1059
  }
 
1060
  return 0;
 
1061
}
 
1062
 
 
1063
 
 
1064
/**
 
1065
  @brief    Calculates lookup values from 'WHERE' condition
 
1066
 
 
1067
  @details This function calculates lookup value(database name, table name)
 
1068
           from 'WHERE' condition if it's possible and
 
1069
           fill lookup_field_vals struct fields with these values.
 
1070
 
 
1071
  @param[in]      session                   thread Cursor
 
1072
  @param[in]      cond                  WHERE condition
 
1073
  @param[in]      table                 I_S table
 
1074
  @param[in, out] lookup_field_vals     Struct which holds lookup values
 
1075
 
 
1076
  @return
 
1077
    0             success
 
1078
    1             error, there can be no matching records for the condition
 
1079
*/
 
1080
 
 
1081
bool calc_lookup_values_from_cond(Session *session, COND *cond, TableList *table,
 
1082
                                  LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1083
                                  plugin::InfoSchemaTable *schema_table)
 
1084
{
 
1085
  if (!cond)
 
1086
    return 0;
 
1087
 
 
1088
  if (cond->type() == Item::COND_ITEM)
 
1089
  {
 
1090
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
1091
    {
 
1092
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1093
      Item *item;
 
1094
      while ((item= li++))
 
1095
      {
 
1096
        if (item->type() == Item::FUNC_ITEM)
 
1097
        {
 
1098
          if (get_lookup_value(session, (Item_func*)item, table, lookup_field_vals, schema_table))
 
1099
            return 1;
 
1100
        }
 
1101
        else
 
1102
        {
 
1103
          if (calc_lookup_values_from_cond(session, item, table, lookup_field_vals, schema_table))
 
1104
            return 1;
 
1105
        }
 
1106
      }
 
1107
    }
 
1108
    return 0;
 
1109
  }
 
1110
  else if (cond->type() == Item::FUNC_ITEM &&
 
1111
           get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals, schema_table))
 
1112
    return 1;
 
1113
  return 0;
 
1114
}
 
1115
 
 
1116
 
 
1117
static bool uses_only_table_name_fields(Item *item, Table *table, plugin::InfoSchemaTable *schema_table)
 
1118
{
 
1119
  if (item->type() == Item::FUNC_ITEM)
 
1120
  {
 
1121
    Item_func *item_func= (Item_func*)item;
 
1122
    for (uint32_t i=0; i<item_func->argument_count(); i++)
 
1123
    {
 
1124
      if (! uses_only_table_name_fields(item_func->arguments()[i], table, schema_table))
 
1125
        return 0;
 
1126
    }
 
1127
  }
 
1128
  else if (item->type() == Item::FIELD_ITEM)
 
1129
  {
 
1130
    Item_field *item_field= (Item_field*)item;
 
1131
    const CHARSET_INFO * const cs= system_charset_info;
 
1132
    const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1133
      schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1134
    const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1135
      schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
 
1136
    if (table != item_field->field->table ||
 
1137
        (cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
 
1138
                               (unsigned char *) item_field->field_name,
 
1139
                               strlen(item_field->field_name), 0) &&
 
1140
         cs->coll->strnncollsp(cs, (unsigned char *) field_name2, strlen(field_name2),
 
1141
                               (unsigned char *) item_field->field_name,
 
1142
                               strlen(item_field->field_name), 0)))
 
1143
      return 0;
 
1144
  }
 
1145
  else if (item->type() == Item::REF_ITEM)
 
1146
    return uses_only_table_name_fields(item->real_item(), table, schema_table);
 
1147
 
 
1148
  if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
 
1149
    return 0;
 
1150
 
 
1151
  return 1;
 
1152
}
 
1153
 
 
1154
 
 
1155
static COND * make_cond_for_info_schema(COND *cond, Table *table, plugin::InfoSchemaTable *schema_table)
 
1156
{
 
1157
  if (!cond)
 
1158
    return (COND*) 0;
 
1159
  if (cond->type() == Item::COND_ITEM)
 
1160
  {
 
1161
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
1162
    {
 
1163
      /* Create new top level AND item */
 
1164
      Item_cond_and *new_cond=new Item_cond_and;
 
1165
      if (!new_cond)
 
1166
        return (COND*) 0;
 
1167
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1168
      Item *item;
 
1169
      while ((item=li++))
 
1170
      {
 
1171
        Item *fix= make_cond_for_info_schema(item, table, schema_table);
 
1172
        if (fix)
 
1173
          new_cond->argument_list()->push_back(fix);
 
1174
      }
 
1175
      switch (new_cond->argument_list()->elements) {
 
1176
        case 0:
 
1177
          return (COND*) 0;
 
1178
        case 1:
 
1179
          return new_cond->argument_list()->head();
 
1180
        default:
 
1181
          new_cond->quick_fix_field();
 
1182
          return new_cond;
 
1183
      }
 
1184
    }
 
1185
    else
 
1186
    {                                           // Or list
 
1187
      Item_cond_or *new_cond=new Item_cond_or;
 
1188
      if (!new_cond)
 
1189
        return (COND*) 0;
 
1190
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1191
      Item *item;
 
1192
      while ((item=li++))
 
1193
      {
 
1194
        Item *fix=make_cond_for_info_schema(item, table, schema_table);
 
1195
        if (!fix)
 
1196
          return (COND*) 0;
 
1197
        new_cond->argument_list()->push_back(fix);
 
1198
      }
 
1199
      new_cond->quick_fix_field();
 
1200
      new_cond->top_level_item();
 
1201
      return new_cond;
 
1202
    }
 
1203
  }
 
1204
 
 
1205
  if (! uses_only_table_name_fields(cond, table, schema_table))
 
1206
    return (COND*) 0;
 
1207
  return cond;
 
1208
}
 
1209
 
 
1210
 
 
1211
/**
 
1212
  @brief   Calculate lookup values(database name, table name)
 
1213
 
 
1214
  @details This function calculates lookup values(database name, table name)
 
1215
           from 'WHERE' condition or wild values (for 'SHOW' commands only)
 
1216
           from LEX struct and fill lookup_field_vals struct field
 
1217
           with these values.
 
1218
 
 
1219
  @param[in]      session                   thread Cursor
 
1220
  @param[in]      cond                  WHERE condition
 
1221
  @param[in]      tables                I_S table
 
1222
  @param[in, out] lookup_field_values   Struct which holds lookup values
 
1223
 
 
1224
  @return
 
1225
    0             success
 
1226
    1             error, there can be no matching records for the condition
 
1227
*/
 
1228
 
 
1229
bool get_lookup_field_values(Session *session, COND *cond, TableList *tables,
 
1230
                             LOOKUP_FIELD_VALUES *lookup_field_values,
 
1231
                             plugin::InfoSchemaTable *schema_table)
 
1232
{
 
1233
  LEX *lex= session->lex;
 
1234
  memset(lookup_field_values, 0, sizeof(LOOKUP_FIELD_VALUES));
 
1235
  switch (lex->sql_command) {
 
1236
    default:
 
1237
    return calc_lookup_values_from_cond(session, cond, tables, lookup_field_values, schema_table);
 
1238
  }
 
1239
}
 
1240
 
 
1241
 
 
1242
/**
 
1243
 * Function used for sorting with std::sort within make_db_list.
 
1244
 *
 
1245
 * @returns true if a < b, false otherwise
 
1246
 */
 
1247
 
 
1248
static bool lex_string_sort(const LEX_STRING *a, const LEX_STRING *b)
 
1249
{
 
1250
  return (strcmp(a->str, b->str) < 0);
 
1251
}
 
1252
 
 
1253
 
 
1254
/**
 
1255
 * @brief
 
1256
 *   Create db names list. Information schema name always is first in list
 
1257
 *
 
1258
 * @param[in]  session          Thread Cursor
 
1259
 * @param[out] files            List of db names
 
1260
 * @param[in]  wild             Wild string
 
1261
 * @param[in]  idx_field_vals   idx_field_vals->db_name contains db name or
 
1262
 *                              wild string
 
1263
 * @param[out] with_i_schema    Returns 1 if we added 'IS' name to list
 
1264
 *                              otherwise returns 0
 
1265
 *
 
1266
 * @retval 0   Success
 
1267
 * @retval 1   Error
 
1268
 */
 
1269
int make_db_list(Session *session, vector<LEX_STRING*> &files,
 
1270
                 LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1271
                 bool *with_i_schema)
 
1272
{
 
1273
  LEX_STRING *i_s_name_copy= 0;
 
1274
  i_s_name_copy= session->make_lex_string(i_s_name_copy,
 
1275
                                      INFORMATION_SCHEMA_NAME.c_str(),
 
1276
                                      INFORMATION_SCHEMA_NAME.length(), true);
 
1277
  *with_i_schema= 0;
 
1278
  if (lookup_field_vals->wild_db_value)
 
1279
  {
 
1280
    /*
 
1281
      This part of code is only for SHOW DATABASES command.
 
1282
      idx_field_vals->db_value can be 0 when we don't use
 
1283
      LIKE clause (see also get_index_field_values() function)
 
1284
    */
 
1285
    if (!lookup_field_vals->db_value.str ||
 
1286
        !wild_case_compare(system_charset_info,
 
1287
                           INFORMATION_SCHEMA_NAME.c_str(),
 
1288
                           lookup_field_vals->db_value.str))
 
1289
    {
 
1290
      *with_i_schema= 1;
 
1291
      files.push_back(i_s_name_copy);
 
1292
    }
 
1293
 
 
1294
    if (find_schemas(session, files, drizzle_data_home,
 
1295
                     lookup_field_vals->db_value.str) == true)
 
1296
    {
 
1297
      return 1;
 
1298
    }
 
1299
 
 
1300
    sort(files.begin()+1, files.end(), lex_string_sort);
 
1301
    return 0;
 
1302
  }
 
1303
 
 
1304
 
 
1305
  /*
 
1306
    If we have db lookup vaule we just add it to list and
 
1307
    exit from the function
 
1308
  */
 
1309
  if (lookup_field_vals->db_value.str)
 
1310
  {
 
1311
    if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.c_str(),
 
1312
                       lookup_field_vals->db_value.str))
 
1313
    {
 
1314
      *with_i_schema= 1;
 
1315
      files.push_back(i_s_name_copy);
 
1316
      return 0;
 
1317
    }
 
1318
 
 
1319
    files.push_back(&lookup_field_vals->db_value);
 
1320
    return 0;
 
1321
  }
 
1322
 
 
1323
  /*
 
1324
    Create list of existing databases. It is used in case
 
1325
    of select from information schema table
 
1326
  */
 
1327
  files.push_back(i_s_name_copy);
 
1328
 
 
1329
  *with_i_schema= 1;
 
1330
 
 
1331
  if (find_schemas(session, files, drizzle_data_home, NULL) == true)
 
1332
  {
 
1333
    return 1;
 
1334
  }
 
1335
 
 
1336
  sort(files.begin()+1, files.end(), lex_string_sort);
 
1337
  return 0;
 
1338
}
 
1339
 
 
1340
 
 
1341
/**
 
1342
  @brief          Create table names list
 
1343
 
 
1344
  @details        The function creates the list of table names in
 
1345
                  database
 
1346
 
 
1347
  @param[in]      session                   thread Cursor
 
1348
  @param[in]      table_names           List of table names in database
 
1349
  @param[in]      lex                   pointer to LEX struct
 
1350
  @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
 
1351
  @param[in]      with_i_schema         true means that we add I_S tables to list
 
1352
  @param[in]      db_name               database name
 
1353
 
 
1354
  @return         Operation status
 
1355
    @retval       0           ok
 
1356
    @retval       1           fatal error
 
1357
    @retval       2           Not fatal error; Safe to ignore this cursor list
 
1358
*/
 
1359
 
 
1360
static int
 
1361
make_table_name_list(Session *session, vector<LEX_STRING*> &table_names,
 
1362
                     LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1363
                     bool with_i_schema, LEX_STRING *db_name)
 
1364
{
 
1365
  char path[FN_REFLEN];
 
1366
  set<string> set_of_names;
 
1367
 
 
1368
  build_table_filename(path, sizeof(path), db_name->str, "", false);
 
1369
 
 
1370
  if (!lookup_field_vals->wild_table_value &&
 
1371
      lookup_field_vals->table_value.str)
 
1372
  {
 
1373
    if (with_i_schema)
 
1374
    {
 
1375
      if (plugin::InfoSchemaTable::getTable(lookup_field_vals->table_value.str))
 
1376
      {
 
1377
        table_names.push_back(&lookup_field_vals->table_value);
 
1378
      }
 
1379
    }
 
1380
    else
 
1381
    {
 
1382
      table_names.push_back(&lookup_field_vals->table_value);
 
1383
    }
 
1384
    return 0;
 
1385
  }
 
1386
 
 
1387
  string db(db_name->str);
 
1388
  plugin::StorageEngine::getTableNames(db, set_of_names);
 
1389
 
 
1390
  /*  
 
1391
    New I_S engine will make this go away, so ignore lack of foreach() usage.
 
1392
 
 
1393
    Notice how bad this design is... sure we created a set... but then we
 
1394
    are just pushing to another set. --
 
1395
    Also... callback design won't work, so we need to rewrite this to
 
1396
    feed (which means new I_S). For the moment we will not optimize this.
 
1397
 
 
1398
  */
 
1399
  for (set<string>::iterator it= set_of_names.begin(); it != set_of_names.end(); it++)
 
1400
  {
 
1401
    LEX_STRING *file_name= NULL;
 
1402
    
 
1403
    file_name= session->make_lex_string(file_name, (*it).c_str(),
 
1404
                                        (*it).length(), true);
 
1405
    const char* wild= lookup_field_vals->table_value.str;
 
1406
    if (wild && internal::wild_compare((*it).c_str(), wild, 0))
 
1407
      continue;
 
1408
 
 
1409
    table_names.push_back(file_name);
 
1410
  }
 
1411
 
 
1412
  return 0;
 
1413
}
 
1414
 
 
1415
 
 
1416
/**
 
1417
  @brief          Fill I_S table for SHOW COLUMNS|INDEX commands
 
1418
 
 
1419
  @param[in]      session                      thread Cursor
 
1420
  @param[in]      tables                   TableList for I_S table
 
1421
  @param[in]      schema_table             pointer to I_S structure
 
1422
  @param[in]      open_tables_state_backup pointer to Open_tables_state object
 
1423
                                           which is used to save|restore original
 
1424
                                           status of variables related to
 
1425
                                           open tables state
 
1426
 
 
1427
  @return         Operation status
 
1428
    @retval       0           success
 
1429
    @retval       1           error
 
1430
*/
 
1431
 
 
1432
static int
 
1433
fill_schema_show_cols_or_idxs(Session *session, TableList *tables,
 
1434
                              plugin::InfoSchemaTable *schema_table,
 
1435
                              Open_tables_state *open_tables_state_backup)
 
1436
{
 
1437
  LEX *lex= session->lex;
 
1438
  bool res;
 
1439
  LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
 
1440
  enum_sql_command save_sql_command= lex->sql_command;
 
1441
  TableList *show_table_list= (TableList*) tables->schema_select_lex->
 
1442
    table_list.first;
 
1443
  Table *table= tables->table;
 
1444
  int error= 1;
 
1445
 
 
1446
  lex->all_selects_list= tables->schema_select_lex;
 
1447
  /*
 
1448
    Restore session->temporary_tables to be able to process
 
1449
    temporary tables(only for 'show index' & 'show columns').
 
1450
    This should be changed when processing of temporary tables for
 
1451
    I_S tables will be done.
 
1452
  */
 
1453
  session->temporary_tables= open_tables_state_backup->temporary_tables;
 
1454
  /*
 
1455
    Let us set fake sql_command so views won't try to merge
 
1456
    themselves into main statement. If we don't do this,
 
1457
    SELECT * from information_schema.xxxx will cause problems.
 
1458
    SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
 
1459
  */
 
1460
  lex->sql_command= SQLCOM_SHOW_FIELDS;
 
1461
  res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
 
1462
  lex->sql_command= save_sql_command;
 
1463
  /*
 
1464
    get_all_tables() returns 1 on failure and 0 on success thus
 
1465
    return only these and not the result code of ::process_table()
 
1466
 
 
1467
    We should use show_table_list->alias instead of
 
1468
    show_table_list->table_name because table_name
 
1469
    could be changed during opening of I_S tables. It's safe
 
1470
    to use alias because alias contains original table name
 
1471
    in this case(this part of code is used only for
 
1472
    'show columns' & 'show statistics' commands).
 
1473
  */
 
1474
   table_name= session->make_lex_string(&tmp_lex_string1, show_table_list->alias,
 
1475
                                    strlen(show_table_list->alias), false);
 
1476
   db_name= session->make_lex_string(&tmp_lex_string, show_table_list->db,
 
1477
                                 show_table_list->db_length, false);
 
1478
 
 
1479
 
 
1480
   table->setWriteSet();
 
1481
   error= test(schema_table->processTable(session, show_table_list,
 
1482
                                          table, res, db_name,
 
1483
                                          table_name));
 
1484
   session->temporary_tables= 0;
 
1485
   session->close_tables_for_reopen(&show_table_list);
 
1486
 
 
1487
   return(error);
 
1488
}
 
1489
 
 
1490
 
 
1491
/**
 
1492
  @brief          Fill I_S table for SHOW Table NAMES commands
 
1493
 
 
1494
  @param[in]      session                      thread Cursor
 
1495
  @param[in]      table                    Table struct for I_S table
 
1496
  @param[in]      db_name                  database name
 
1497
  @param[in]      table_name               table name
 
1498
  @param[in]      with_i_schema            I_S table if true
 
1499
 
 
1500
  @return         Operation status
 
1501
    @retval       0           success
 
1502
    @retval       1           error
 
1503
*/
 
1504
 
 
1505
static int fill_schema_table_names(Session *session, Table *table,
 
1506
                                   LEX_STRING *db_name, LEX_STRING *table_name,
 
1507
                                   bool with_i_schema,
 
1508
                                   plugin::InfoSchemaTable *schema_table)
 
1509
{
 
1510
  if (with_i_schema)
 
1511
  {
 
1512
    table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
 
1513
                           system_charset_info);
 
1514
  }
 
1515
  else
 
1516
  {
 
1517
    char path[FN_REFLEN];
 
1518
    (void) build_table_filename(path, sizeof(path), db_name->str,
 
1519
                                table_name->str, false);
 
1520
 
 
1521
      table->field[3]->store(STRING_WITH_LEN("BASE Table"),
 
1522
                             system_charset_info);
 
1523
 
 
1524
    if (session->is_error() && session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
1525
    {
 
1526
      session->clear_error();
 
1527
      return 0;
 
1528
    }
 
1529
  }
 
1530
  schema_table->addRow(table->record[0], table->s->reclength);
 
1531
  return 0;
 
1532
}
 
1533
 
 
1534
int plugin::InfoSchemaMethods::fillTable(Session *session,
 
1535
                                         Table *table,
 
1536
                                         plugin::InfoSchemaTable *schema_table)
 
1537
{
 
1538
  LEX *lex= session->lex;
 
1539
  Select_Lex *old_all_select_lex= lex->all_selects_list;
 
1540
  enum_sql_command save_sql_command= lex->sql_command;
 
1541
  Select_Lex *lsel= table->pos_in_table_list->schema_select_lex;
 
1542
  Select_Lex sel;
 
1543
  LOOKUP_FIELD_VALUES lookup_field_vals;
 
1544
  bool with_i_schema;
 
1545
  vector<LEX_STRING*> db_names, table_names;
 
1546
  /* the WHERE clause */
 
1547
  COND *cond= table->reginfo.join_tab->select_cond;
 
1548
  COND *partial_cond= 0;
 
1549
  uint32_t derived_tables= lex->derived_tables;
 
1550
  int error= 1;
 
1551
  Open_tables_state open_tables_state_backup;
 
1552
  Query_tables_list query_tables_list_backup;
 
1553
  bool old_value= session->no_warnings_for_error;
 
1554
 
 
1555
  /*
 
1556
    We should not introduce deadlocks even if we already have some
 
1557
    tables open and locked, since we won't lock tables which we will
 
1558
    open and will ignore possible name-locks for these tables.
 
1559
  */
 
1560
  session->reset_n_backup_open_tables_state(&open_tables_state_backup);
 
1561
 
 
1562
  /*
 
1563
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
 
1564
    see sql_parse.cc, prepare_schema_table() function where
 
1565
    this values are initialized
 
1566
  */
 
1567
  if (lsel && lsel->table_list.first)
 
1568
  {
 
1569
    error= fill_schema_show_cols_or_idxs(session, table->pos_in_table_list, schema_table,
 
1570
                                         &open_tables_state_backup);
 
1571
    goto err;
 
1572
  }
 
1573
 
 
1574
  if (get_lookup_field_values(session, 
 
1575
                              cond, 
 
1576
                              table->pos_in_table_list, 
 
1577
                              &lookup_field_vals,
 
1578
                              schema_table))
 
1579
  {
 
1580
    error= 0;
 
1581
    goto err;
 
1582
  }
 
1583
 
 
1584
  if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
 
1585
  {
 
1586
    /*
 
1587
      if lookup value is empty string then
 
1588
      it's impossible table name or db name
 
1589
    */
 
1590
    if ((lookup_field_vals.db_value.str && !lookup_field_vals.db_value.str[0]) ||
 
1591
        (lookup_field_vals.table_value.str && !lookup_field_vals.table_value.str[0]))
 
1592
    {
 
1593
      error= 0;
 
1594
      goto err;
 
1595
    }
 
1596
  }
 
1597
 
 
1598
  if (lookup_field_vals.db_value.length &&
 
1599
      !lookup_field_vals.wild_db_value)
 
1600
    table->pos_in_table_list->has_db_lookup_value= true;
 
1601
 
 
1602
  if (lookup_field_vals.table_value.length &&
 
1603
      !lookup_field_vals.wild_table_value)
 
1604
    table->pos_in_table_list->has_table_lookup_value= true;
 
1605
 
 
1606
  if (table->pos_in_table_list->has_db_lookup_value && 
 
1607
      table->pos_in_table_list->has_table_lookup_value)
 
1608
    partial_cond= 0;
 
1609
  else
 
1610
    partial_cond= make_cond_for_info_schema(cond, table, schema_table);
 
1611
 
 
1612
  if (lex->describe)
 
1613
  {
 
1614
    /* EXPLAIN SELECT */
 
1615
    error= 0;
 
1616
    goto err;
 
1617
  }
 
1618
 
 
1619
  table->setWriteSet();
 
1620
  if (make_db_list(session, db_names, &lookup_field_vals, &with_i_schema))
 
1621
    goto err;
 
1622
 
 
1623
  for (vector<LEX_STRING*>::iterator db_name= db_names.begin(); db_name != db_names.end(); ++db_name )
 
1624
  {
 
1625
    session->no_warnings_for_error= 1;
 
1626
    table_names.clear();
 
1627
    int res= make_table_name_list(session, table_names,
 
1628
                                  &lookup_field_vals,
 
1629
                                  with_i_schema, *db_name);
 
1630
 
 
1631
    if (res == 2)   /* Not fatal error, continue */
 
1632
      continue;
 
1633
 
 
1634
    if (res)
 
1635
      goto err;
 
1636
 
 
1637
    
 
1638
    for (vector<LEX_STRING*>::iterator table_name= table_names.begin(); table_name != table_names.end(); ++table_name)
 
1639
    {
 
1640
      table->restoreRecordAsDefault();
 
1641
      table->field[schema_table->getFirstColumnIndex()]->
 
1642
        store((*db_name)->str, (*db_name)->length, system_charset_info);
 
1643
      table->field[schema_table->getSecondColumnIndex()]->
 
1644
        store((*table_name)->str, (*table_name)->length, system_charset_info);
 
1645
 
 
1646
      if (!partial_cond || partial_cond->val_int())
 
1647
      {
 
1648
        /* SHOW Table NAMES command */
 
1649
        if (schema_table->getTableName().compare("TABLE_NAMES") == 0)
 
1650
        {
 
1651
          if (fill_schema_table_names(session, 
 
1652
                                      table, 
 
1653
                                      *db_name,
 
1654
                                      *table_name, 
 
1655
                                      with_i_schema,
 
1656
                                      schema_table))
 
1657
            continue;
 
1658
        }
 
1659
        else
 
1660
        {
 
1661
          LEX_STRING tmp_lex_string, orig_db_name;
 
1662
          /*
 
1663
            Set the parent lex of 'sel' because it is needed by
 
1664
            sel.init_query() which is called inside make_table_list.
 
1665
          */
 
1666
          session->no_warnings_for_error= 1;
 
1667
          sel.parent_lex= lex;
 
1668
          /* db_name can be changed in make_table_list() func */
 
1669
          if (! session->make_lex_string(&orig_db_name, 
 
1670
                                         (*db_name)->str,
 
1671
                                         (*db_name)->length, 
 
1672
                                         false))
 
1673
          {
 
1674
            goto err;
 
1675
          }
 
1676
 
 
1677
          if (make_table_list(session, &sel, *db_name, *table_name))
 
1678
            goto err;
 
1679
 
 
1680
          TableList *show_table_list= (TableList*) sel.table_list.first;
 
1681
          lex->all_selects_list= &sel;
 
1682
          lex->derived_tables= 0;
 
1683
          lex->sql_command= SQLCOM_SHOW_FIELDS;
 
1684
          show_table_list->i_s_requested_object=
 
1685
            schema_table->getRequestedObject();
 
1686
          res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
 
1687
          lex->sql_command= save_sql_command;
 
1688
          /*
 
1689
            XXX->  show_table_list has a flag i_is_requested,
 
1690
            and when it's set, openTables()
 
1691
            can return an error without setting an error message
 
1692
            in Session, which is a hack. This is why we have to
 
1693
            check for res, then for session->is_error() only then
 
1694
            for session->main_da.sql_errno().
 
1695
          */
 
1696
          if (res && session->is_error() &&
 
1697
              session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
1698
          {
 
1699
            /*
 
1700
              Hide error for not existing table.
 
1701
              This error can occur for example when we use
 
1702
              where condition with db name and table name and this
 
1703
              table does not exist.
 
1704
            */
 
1705
            res= 0;
 
1706
            session->clear_error();
 
1707
          }
 
1708
          else
 
1709
          {
 
1710
            /*
 
1711
              We should use show_table_list->alias instead of
 
1712
              show_table_list->table_name because table_name
 
1713
              could be changed during opening of I_S tables. It's safe
 
1714
              to use alias because alias contains original table name
 
1715
              in this case.
 
1716
            */
 
1717
            session->make_lex_string(&tmp_lex_string, show_table_list->alias,
 
1718
                                     strlen(show_table_list->alias), false);
 
1719
            res= schema_table->processTable(session, show_table_list, table,
 
1720
                                            res, &orig_db_name,
 
1721
                                            &tmp_lex_string);
 
1722
            session->close_tables_for_reopen(&show_table_list);
 
1723
          }
 
1724
          assert(!lex->query_tables_own_last);
 
1725
          if (res)
 
1726
            goto err;
 
1727
        }
 
1728
      }
 
1729
    }
 
1730
    /*
 
1731
      If we have information schema its always the first table and only
 
1732
      the first table. Reset for other tables.
 
1733
    */
 
1734
    with_i_schema= 0;
 
1735
  }
 
1736
 
 
1737
  error= 0;
 
1738
 
 
1739
err:
 
1740
  session->restore_backup_open_tables_state(&open_tables_state_backup);
 
1741
  lex->derived_tables= derived_tables;
 
1742
  lex->all_selects_list= old_all_select_lex;
 
1743
  lex->sql_command= save_sql_command;
 
1744
  session->no_warnings_for_error= old_value;
 
1745
  return(error);
 
1746
}
 
1747
 
 
1748
 
 
1749
/**
 
1750
  @brief    Store field characteristics into appropriate I_S table columns
 
1751
 
 
1752
  @param[in]      table             I_S table
 
1753
  @param[in]      field             processed field
 
1754
  @param[in]      cs                I_S table charset
 
1755
  @param[in]      offset            offset from beginning of table
 
1756
                                    to DATE_TYPE column in I_S table
 
1757
 
 
1758
  @return         void
 
1759
*/
 
1760
 
 
1761
static void store_column_type(Table *table, Field *field,
 
1762
                              const CHARSET_INFO * const cs,
 
1763
                              uint32_t offset)
 
1764
{
 
1765
  bool is_blob;
 
1766
  int decimals, field_length;
 
1767
  const char *tmp_buff;
 
1768
  char column_type_buff[MAX_FIELD_WIDTH];
 
1769
  String column_type(column_type_buff, sizeof(column_type_buff), cs);
 
1770
 
 
1771
  field->sql_type(column_type);
 
1772
  /* DTD_IDENTIFIER column */
 
1773
  table->field[offset + 7]->store(column_type.ptr(), column_type.length(), cs);
 
1774
  table->field[offset + 7]->set_notnull();
 
1775
  tmp_buff= strchr(column_type.ptr(), '(');
 
1776
  /* DATA_TYPE column */
 
1777
  table->field[offset]->store(column_type.ptr(),
 
1778
                         (tmp_buff ? tmp_buff - column_type.ptr() :
 
1779
                          column_type.length()), cs);
 
1780
  is_blob= (field->type() == DRIZZLE_TYPE_BLOB);
 
1781
  if (field->has_charset() || is_blob ||
 
1782
      field->real_type() == DRIZZLE_TYPE_VARCHAR)  // For varbinary type
 
1783
  {
 
1784
    uint32_t octet_max_length= field->max_display_length();
 
1785
    if (is_blob && octet_max_length != (uint32_t) 4294967295U)
 
1786
      octet_max_length /= field->charset()->mbmaxlen;
 
1787
    int64_t char_max_len= is_blob ?
 
1788
      (int64_t) octet_max_length / field->charset()->mbminlen :
 
1789
      (int64_t) octet_max_length / field->charset()->mbmaxlen;
 
1790
    /* CHARACTER_MAXIMUM_LENGTH column*/
 
1791
    table->field[offset + 1]->store(char_max_len, true);
 
1792
    table->field[offset + 1]->set_notnull();
 
1793
    /* CHARACTER_OCTET_LENGTH column */
 
1794
    table->field[offset + 2]->store((int64_t) octet_max_length, true);
 
1795
    table->field[offset + 2]->set_notnull();
 
1796
  }
 
1797
 
 
1798
  /*
 
1799
    Calculate field_length and decimals.
 
1800
    They are set to -1 if they should not be set (we should return NULL)
 
1801
  */
 
1802
 
 
1803
  decimals= field->decimals();
 
1804
  switch (field->type()) {
 
1805
  case DRIZZLE_TYPE_DECIMAL:
 
1806
    field_length= ((Field_decimal*) field)->precision;
 
1807
    break;
 
1808
  case DRIZZLE_TYPE_LONG:
 
1809
  case DRIZZLE_TYPE_LONGLONG:
 
1810
    field_length= field->max_display_length() - 1;
 
1811
    break;
 
1812
  case DRIZZLE_TYPE_DOUBLE:
 
1813
    field_length= field->field_length;
 
1814
    if (decimals == NOT_FIXED_DEC)
 
1815
      decimals= -1;                           // return NULL
 
1816
    break;
 
1817
  default:
 
1818
    field_length= decimals= -1;
 
1819
    break;
 
1820
  }
 
1821
 
 
1822
  /* NUMERIC_PRECISION column */
 
1823
  if (field_length >= 0)
 
1824
  {
 
1825
    table->field[offset + 3]->store((int64_t) field_length, true);
 
1826
    table->field[offset + 3]->set_notnull();
 
1827
  }
 
1828
  /* NUMERIC_SCALE column */
 
1829
  if (decimals >= 0)
 
1830
  {
 
1831
    table->field[offset + 4]->store((int64_t) decimals, true);
 
1832
    table->field[offset + 4]->set_notnull();
 
1833
  }
 
1834
  if (field->has_charset())
 
1835
  {
 
1836
    /* CHARACTER_SET_NAME column*/
 
1837
    tmp_buff= field->charset()->csname;
 
1838
    table->field[offset + 5]->store(tmp_buff, strlen(tmp_buff), cs);
 
1839
    table->field[offset + 5]->set_notnull();
 
1840
    /* COLLATION_NAME column */
 
1841
    tmp_buff= field->charset()->name;
 
1842
    table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs);
 
1843
    table->field[offset + 6]->set_notnull();
 
1844
  }
 
1845
}
 
1846
 
 
1847
 
 
1848
int plugin::InfoSchemaMethods::processTable(
 
1849
            plugin::InfoSchemaTable *store_table,
 
1850
            Session *session, 
 
1851
            TableList *tables,
 
1852
                                    Table *table, bool res,
 
1853
                                    LEX_STRING *db_name,
 
1854
                                    LEX_STRING *table_name)
 
1855
{
 
1856
  LEX *lex= session->lex;
 
1857
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
 
1858
  const CHARSET_INFO * const cs= system_charset_info;
 
1859
  Table *show_table;
 
1860
  TableShare *show_table_share;
 
1861
  Field **ptr, *field, *timestamp_field;
 
1862
  int count;
 
1863
 
 
1864
  if (res)
 
1865
  {
 
1866
    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
 
1867
    {
 
1868
      /*
 
1869
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
 
1870
        rather than in SHOW COLUMNS
 
1871
      */
 
1872
      if (session->is_error())
 
1873
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1874
                     session->main_da.sql_errno(), session->main_da.message());
 
1875
      session->clear_error();
 
1876
      res= 0;
 
1877
    }
 
1878
    return(res);
 
1879
  }
 
1880
 
 
1881
  show_table= tables->table;
 
1882
  show_table_share= show_table->s;
 
1883
  count= 0;
 
1884
 
 
1885
  ptr= show_table_share->field;
 
1886
  timestamp_field= show_table_share->timestamp_field;
 
1887
 
 
1888
  /* For the moment we just set everything to read */
 
1889
  if (!show_table->read_set)
 
1890
  {
 
1891
    show_table->def_read_set.setAll();
 
1892
    show_table->read_set= &show_table->def_read_set;
 
1893
  }
 
1894
  show_table->use_all_columns();               // Required for default
 
1895
 
 
1896
  for (; (field= *ptr) ; ptr++)
 
1897
  {
 
1898
    unsigned char *pos;
 
1899
    char tmp[MAX_FIELD_WIDTH];
 
1900
    String type(tmp,sizeof(tmp), system_charset_info);
 
1901
    char *end;
 
1902
 
 
1903
    /* to satisfy 'field->val_str' ASSERTs */
 
1904
    field->table= show_table;
 
1905
    show_table->in_use= session;
 
1906
 
 
1907
    if (wild && wild[0] &&
 
1908
        wild_case_compare(system_charset_info, field->field_name,wild))
 
1909
      continue;
 
1910
 
 
1911
    count++;
 
1912
    /* Get default row, with all NULL fields set to NULL */
 
1913
    table->restoreRecordAsDefault();
 
1914
 
 
1915
    table->field[1]->store(db_name->str, db_name->length, cs);
 
1916
    table->field[2]->store(table_name->str, table_name->length, cs);
 
1917
    table->field[3]->store(field->field_name, strlen(field->field_name),
 
1918
                           cs);
 
1919
    table->field[4]->store((int64_t) count, true);
 
1920
 
 
1921
    if (get_field_default_value(timestamp_field, field, &type, 0))
 
1922
    {
 
1923
      table->field[5]->store(type.ptr(), type.length(), cs);
 
1924
      table->field[5]->set_notnull();
 
1925
    }
 
1926
    pos=(unsigned char*) ((field->flags & NOT_NULL_FLAG) ?  "NO" : "YES");
 
1927
    table->field[6]->store((const char*) pos,
 
1928
                           strlen((const char*) pos), cs);
 
1929
    store_column_type(table, field, cs, 7);
 
1930
 
 
1931
    pos=(unsigned char*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
 
1932
                 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
 
1933
                 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
 
1934
    table->field[15]->store((const char*) pos,
 
1935
                            strlen((const char*) pos), cs);
 
1936
 
 
1937
    end= tmp;
 
1938
    if (field->unireg_check == Field::NEXT_NUMBER)
 
1939
      table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
 
1940
    if (timestamp_field == field &&
 
1941
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
1942
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
 
1943
                              cs);
 
1944
    table->field[18]->store(field->comment.str, field->comment.length, cs);
 
1945
    {
 
1946
      enum column_format_type column_format= (enum column_format_type)
 
1947
        ((field->flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
1948
      pos=(unsigned char*)"Default";
 
1949
      table->field[19]->store((const char*) pos,
 
1950
                              strlen((const char*) pos), cs);
 
1951
      pos=(unsigned char*)(column_format == COLUMN_FORMAT_TYPE_DEFAULT ? "Default" :
 
1952
                   column_format == COLUMN_FORMAT_TYPE_FIXED ? "Fixed" :
 
1953
                                                             "Dynamic");
 
1954
      table->field[20]->store((const char*) pos,
 
1955
                              strlen((const char*) pos), cs);
 
1956
    }
 
1957
    store_table->addRow(table->record[0], table->s->reclength);
 
1958
  }
 
1959
  return(0);
 
1960
}
 
1961
 
 
1962
 
 
1963
/*
 
1964
  For old SHOW compatibility. It is used when
 
1965
  old SHOW doesn't have generated column names
 
1966
  Make list of fields for SHOW
 
1967
 
 
1968
  SYNOPSIS
 
1969
    plugin::InfoSchemaMethods::oldFormat()
 
1970
    session                     thread Cursor
 
1971
    schema_table        pointer to 'schema_tables' element
 
1972
 
 
1973
  RETURN
 
1974
   1    error
 
1975
   0    success
 
1976
*/
 
1977
 
 
1978
int plugin::InfoSchemaMethods::oldFormat(Session *session, plugin::InfoSchemaTable *schema_table)
 
1979
  const
 
1980
{
 
1981
  Name_resolution_context *context= &session->lex->select_lex.context;
 
1982
  const plugin::InfoSchemaTable::Columns columns= schema_table->getColumns();
 
1983
  plugin::InfoSchemaTable::Columns::const_iterator iter= columns.begin();
 
1984
 
 
1985
  while (iter != columns.end())
 
1986
  {
 
1987
    const plugin::ColumnInfo *column= *iter;
 
1988
    if (column->getOldName().length() != 0)
 
1989
    {
 
1990
      Item_field *field= new Item_field(context,
 
1991
                                        NULL, NULL,
 
1992
                                        column->getName().c_str());
 
1993
      if (field)
 
1994
      {
 
1995
        field->set_name(column->getOldName().c_str(),
 
1996
                        column->getOldName().length(),
 
1997
                        system_charset_info);
 
1998
        if (session->add_item_to_list(field))
 
1999
          return 1;
 
2000
      }
 
2001
    }
 
2002
    ++iter;
 
2003
  }
 
2004
  return 0;
 
2005
}
 
2006
 
 
2007
 
 
2008
/*
 
2009
  Generate select from information_schema table
 
2010
 
 
2011
  SYNOPSIS
 
2012
    make_schema_select()
 
2013
    session                  thread Cursor
 
2014
    sel                  pointer to Select_Lex
 
2015
    schema_table_name    name of 'schema_tables' element
 
2016
 
 
2017
  RETURN
 
2018
    true on error
 
2019
*/
 
2020
 
 
2021
bool make_schema_select(Session *session, Select_Lex *sel,
 
2022
                        const string& schema_table_name)
 
2023
{
 
2024
  plugin::InfoSchemaTable *schema_table= plugin::InfoSchemaTable::getTable(schema_table_name.c_str());
 
2025
  LEX_STRING db, table;
 
2026
  /*
 
2027
     We have to make non const db_name & table_name
 
2028
     because of lower_case_table_names
 
2029
  */
 
2030
  session->make_lex_string(&db, INFORMATION_SCHEMA_NAME.c_str(),
 
2031
                       INFORMATION_SCHEMA_NAME.length(), 0);
 
2032
  session->make_lex_string(&table, schema_table->getTableName().c_str(),
 
2033
                           schema_table->getTableName().length(), 0);
 
2034
  if (schema_table->oldFormat(session, schema_table) ||   /* Handle old syntax */
 
2035
      ! sel->add_table_to_list(session, new Table_ident(db, table), 0, 0, TL_READ))
 
2036
  {
 
2037
    return true;
 
2038
  }
294
2039
  return false;
295
2040
}
296
2041
 
297
 
bool buildColumns(Session *session, const char *schema_ident, Table_ident *table_ident)
298
 
{
299
 
  session->getLex()->sql_command= SQLCOM_SELECT;
300
 
 
301
 
  drizzled::statement::Show *select= new statement::Show(session);
302
 
  session->getLex()->statement= select;
303
 
 
304
 
  util::string::const_shared_ptr schema(session->schema());
305
 
  if (schema_ident)
306
 
  {
307
 
    select->setShowPredicate(schema_ident, table_ident->table.str);
308
 
  }
309
 
  else if (table_ident->db.str)
310
 
  {
311
 
    select->setShowPredicate(table_ident->db.str, table_ident->table.str);
312
 
  }
313
 
  else if (schema)
314
 
  {
315
 
    select->setShowPredicate(*schema, table_ident->table.str);
316
 
  }
317
 
  else
318
 
  {
319
 
    my_error(ER_NO_DB_ERROR, MYF(0));
320
 
    return false;
321
 
  }
322
 
 
323
 
  {
324
 
    drizzled::identifier::Table identifier(select->getShowSchema().c_str(), table_ident->table.str);
325
 
    if (not plugin::StorageEngine::doesTableExist(*session, identifier))
326
 
    {
327
 
      my_error(ER_TABLE_UNKNOWN, identifier);
328
 
    }
329
 
  }
330
 
 
331
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_COLUMNS"))
332
 
    return false;
333
 
 
334
 
  if (session->add_item_to_list( new Item_field(&session->lex->current_select->context, NULL, NULL, "*")))
335
 
    return false;
336
 
 
337
 
  (session->lex->current_select->with_wild)++;
338
 
 
339
 
  return true;
340
 
}
341
 
 
342
 
void buildSelectWarning(Session *session)
343
 
{
344
 
  (void) create_select_for_variable(session, "warning_count");
345
 
  session->getLex()->statement= new statement::Show(session);
346
 
}
347
 
 
348
 
void buildSelectError(Session *session)
349
 
{
350
 
  (void) create_select_for_variable(session, "error_count");
351
 
  session->getLex()->statement= new statement::Show(session);
352
 
}
353
 
 
354
 
void buildWarnings(Session *session)
355
 
{
356
 
  session->getLex()->statement= new statement::ShowWarnings(session);
357
 
}
358
 
 
359
 
void buildErrors(Session *session)
360
 
{
361
 
  session->getLex()->statement= new statement::ShowErrors(session);
362
 
}
363
 
 
364
 
bool buildIndex(Session *session, const char *schema_ident, Table_ident *table_ident)
365
 
{
366
 
  session->getLex()->sql_command= SQLCOM_SELECT;
367
 
  drizzled::statement::Show *select= new statement::Show(session);
368
 
  session->getLex()->statement= select;
369
 
 
370
 
  util::string::const_shared_ptr schema(session->schema());
371
 
  if (schema_ident)
372
 
  {
373
 
    select->setShowPredicate(schema_ident, table_ident->table.str);
374
 
  }
375
 
  else if (table_ident->db.str)
376
 
  {
377
 
    select->setShowPredicate(table_ident->db.str, table_ident->table.str);
378
 
  }
379
 
  else if (schema)
380
 
  {
381
 
    select->setShowPredicate(*schema, table_ident->table.str);
382
 
  }
383
 
  else
384
 
  {
385
 
    my_error(ER_NO_DB_ERROR, MYF(0));
386
 
    return false;
387
 
  }
388
 
 
389
 
  {
390
 
    drizzled::identifier::Table identifier(select->getShowSchema().c_str(), table_ident->table.str);
391
 
    if (not plugin::StorageEngine::doesTableExist(*session, identifier))
392
 
    {
393
 
      my_error(ER_TABLE_UNKNOWN, identifier);
394
 
    }
395
 
  }
396
 
 
397
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_INDEXES"))
398
 
    return false;
399
 
 
400
 
  if (session->add_item_to_list( new Item_field(&session->lex->current_select->context, NULL, NULL, "*")))
401
 
    return false;
402
 
 
403
 
  (session->lex->current_select->with_wild)++;
404
 
 
405
 
  return true;
406
 
}
407
 
 
408
 
bool buildStatus(Session *session, const drizzled::sql_var_t is_global)
409
 
{
410
 
  session->getLex()->sql_command= SQLCOM_SELECT;
411
 
  session->getLex()->statement= new statement::Show(session);
412
 
 
413
 
  if (is_global == OPT_GLOBAL)
414
 
  {
415
 
    if (prepare_new_schema_table(session, session->getLex(), "GLOBAL_STATUS"))
416
 
      return false;
417
 
  }
418
 
  else
419
 
  {
420
 
    if (prepare_new_schema_table(session, session->getLex(), "SESSION_STATUS"))
421
 
      return false;
422
 
  }
423
 
 
424
 
  std::string key("Variable_name");
425
 
  std::string value("Value");
426
 
 
427
 
  Item_field *my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "VARIABLE_NAME");
428
 
  my_field->is_autogenerated_name= false;
429
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
430
 
 
431
 
  if (session->add_item_to_list(my_field))
432
 
    return false;
433
 
 
434
 
  my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "VARIABLE_VALUE");
435
 
  my_field->is_autogenerated_name= false;
436
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
437
 
 
438
 
  if (session->add_item_to_list(my_field))
439
 
    return false;
440
 
 
441
 
  return true;
442
 
}
443
 
 
444
 
bool buildCreateTable(Session *session, Table_ident *ident)
445
 
{
446
 
  session->getLex()->sql_command= SQLCOM_SELECT;
447
 
  statement::Show *select= new statement::Show(session);
448
 
  session->getLex()->statement= select;
449
 
 
450
 
  if (session->getLex()->statement == NULL)
451
 
    return false;
452
 
 
453
 
  if (prepare_new_schema_table(session, session->getLex(), "TABLE_SQL_DEFINITION"))
454
 
    return false;
455
 
 
456
 
  util::string::const_shared_ptr schema(session->schema());
457
 
  if (ident->db.str)
458
 
  {
459
 
    select->setShowPredicate(ident->db.str, ident->table.str);
460
 
  }
461
 
  else if (schema)
462
 
  {
463
 
    select->setShowPredicate(*schema, ident->table.str);
464
 
  }
465
 
  else
466
 
  {
467
 
    my_error(ER_NO_DB_ERROR, MYF(0));
468
 
    return false;
469
 
  }
470
 
 
471
 
  std::string key("Table");
472
 
  std::string value("Create Table");
473
 
 
474
 
  Item_field *my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "TABLE_NAME");
475
 
  my_field->is_autogenerated_name= false;
476
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
477
 
 
478
 
  if (session->add_item_to_list(my_field))
479
 
    return false;
480
 
 
481
 
  my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "TABLE_SQL_DEFINITION");
482
 
  my_field->is_autogenerated_name= false;
483
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
484
 
 
485
 
  if (session->add_item_to_list(my_field))
486
 
    return false;
487
 
 
488
 
  return true;
489
 
}
490
 
 
491
 
bool buildProcesslist(Session *session)
492
 
{
493
 
  session->getLex()->sql_command= SQLCOM_SELECT;
494
 
  session->getLex()->statement= new statement::Show(session);
495
 
 
496
 
  if (prepare_new_schema_table(session, session->getLex(), "PROCESSLIST"))
497
 
    return false;
498
 
 
499
 
  if (session->add_item_to_list( new Item_field(&session->lex->current_select->context, NULL, NULL, "*")))
500
 
    return false;
501
 
 
502
 
  (session->lex->current_select->with_wild)++;
503
 
 
504
 
  return true;
505
 
}
506
 
 
507
 
bool buildVariables(Session *session, const drizzled::sql_var_t is_global)
508
 
{
509
 
  session->getLex()->sql_command= SQLCOM_SELECT;
510
 
  session->getLex()->statement= new statement::Show(session);
511
 
 
512
 
  if (is_global == OPT_GLOBAL)
513
 
  {
514
 
    if (prepare_new_schema_table(session, session->getLex(), "GLOBAL_VARIABLES"))
515
 
      return false;
516
 
  }
517
 
  else
518
 
  {
519
 
    if (prepare_new_schema_table(session, session->getLex(), "SESSION_VARIABLES"))
520
 
      return false;
521
 
  }
522
 
 
523
 
  std::string key("Variable_name");
524
 
  std::string value("Value");
525
 
 
526
 
  Item_field *my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "VARIABLE_NAME");
527
 
  my_field->is_autogenerated_name= false;
528
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
529
 
 
530
 
  if (session->add_item_to_list(my_field))
531
 
    return false;
532
 
 
533
 
  my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "VARIABLE_VALUE");
534
 
  my_field->is_autogenerated_name= false;
535
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
536
 
 
537
 
  if (session->add_item_to_list(my_field))
538
 
    return false;
539
 
 
540
 
  return true;
541
 
}
542
 
 
543
 
bool buildCreateSchema(Session *session, LEX_STRING &ident)
544
 
{
545
 
  session->getLex()->sql_command= SQLCOM_SELECT;
546
 
  drizzled::statement::Show *select= new statement::Show(session);
547
 
  session->getLex()->statement= select;
548
 
 
549
 
  if (prepare_new_schema_table(session, session->getLex(), "SCHEMA_SQL_DEFINITION"))
550
 
    return false;
551
 
 
552
 
  util::string::const_shared_ptr schema(session->schema());
553
 
  if (ident.str)
554
 
  {
555
 
    select->setShowPredicate(ident.str);
556
 
  }
557
 
  else if (schema)
558
 
  {
559
 
    select->setShowPredicate(*schema);
560
 
  }
561
 
  else
562
 
  {
563
 
    my_error(ER_NO_DB_ERROR, MYF(0));
564
 
    return false;
565
 
  }
566
 
 
567
 
  std::string key("Database");
568
 
  std::string value("Create Database");
569
 
 
570
 
  Item_field *my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "SCHEMA_NAME");
571
 
  my_field->is_autogenerated_name= false;
572
 
  my_field->set_name(key.c_str(), key.length(), system_charset_info);
573
 
 
574
 
  if (session->add_item_to_list(my_field))
575
 
    return false;
576
 
 
577
 
  my_field= new Item_field(&session->lex->current_select->context, NULL, NULL, "SCHEMA_SQL_DEFINITION");
578
 
  my_field->is_autogenerated_name= false;
579
 
  my_field->set_name(value.c_str(), value.length(), system_charset_info);
580
 
 
581
 
  if (session->add_item_to_list(my_field))
582
 
    return false;
583
 
 
584
 
  return true;
585
 
}
586
 
 
587
 
bool buildDescribe(Session *session, Table_ident *ident)
588
 
{
589
 
  session->getLex()->lock_option= TL_READ;
590
 
  init_select(session->getLex());
591
 
  session->getLex()->current_select->parsing_place= SELECT_LIST;
592
 
  session->getLex()->sql_command= SQLCOM_SELECT;
593
 
  drizzled::statement::Show *select= new statement::Show(session);
594
 
  session->getLex()->statement= select;
595
 
  session->getLex()->select_lex.db= 0;
596
 
 
597
 
  util::string::const_shared_ptr schema(session->schema());
598
 
  if (ident->db.str)
599
 
  {
600
 
    select->setShowPredicate(ident->db.str, ident->table.str);
601
 
  }
602
 
  else if (schema)
603
 
  {
604
 
    select->setShowPredicate(*schema, ident->table.str);
605
 
  }
606
 
  else
607
 
  {
608
 
    my_error(ER_NO_DB_ERROR, MYF(0));
609
 
    return false;
610
 
  }
611
 
 
612
 
  {
613
 
    drizzled::identifier::Table identifier(select->getShowSchema().c_str(), ident->table.str);
614
 
    if (not plugin::StorageEngine::doesTableExist(*session, identifier))
615
 
    {
616
 
      my_error(ER_TABLE_UNKNOWN, identifier);
617
 
    }
618
 
  }
619
 
 
620
 
  if (prepare_new_schema_table(session, session->getLex(), "SHOW_COLUMNS"))
621
 
  {
622
 
    return false;
623
 
  }
624
 
 
625
 
  if (session->add_item_to_list( new Item_field(&session->lex->current_select->
626
 
                                                  context,
627
 
                                                  NULL, NULL, "*")))
628
 
  {
629
 
    return false;
630
 
  }
631
 
 
632
 
  (session->lex->current_select->with_wild)++;
633
 
 
634
 
  return true;
635
 
}
636
 
 
637
 
} /* namespace drizzled */
638
 
 
639
2042
} /* namespace drizzled */