~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

Reverted 1103

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2010 Brian Aker
5
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
6
5
 *
7
6
 *  This program is free software; you can redistribute it and/or modify
8
7
 *  it under the terms of the GNU General Public License as published by
20
19
 
21
20
 
22
21
/* Function with list databases, tables or fields */
23
 
#include "config.h"
24
 
 
25
 
#include "drizzled/data_home.h"
26
 
#include "drizzled/error.h"
27
 
#include "drizzled/internal/my_sys.h"
28
 
#include "drizzled/plugin/storage_engine.h"
29
 
#include "drizzled/session.h"
30
 
#include "drizzled/show.h"
31
 
#include "drizzled/sql_select.h"
32
 
 
33
 
#include "drizzled/statement/show.h"
34
 
#include "drizzled/statement/show_errors.h"
35
 
#include "drizzled/statement/show_warnings.h"
36
 
 
37
 
 
38
 
#include <sys/stat.h>
 
22
#include <drizzled/server_includes.h>
 
23
#include <drizzled/sql_select.h>
 
24
#include <drizzled/show.h>
 
25
#include <mysys/my_dir.h>
 
26
#include <drizzled/gettext.h>
 
27
#include <drizzled/util/convert.h>
 
28
#include <drizzled/error.h>
 
29
#include <drizzled/tztime.h>
 
30
#include <drizzled/data_home.h>
 
31
#include <drizzled/item/blob.h>
 
32
#include <drizzled/item/cmpfunc.h>
 
33
#include <drizzled/item/return_int.h>
 
34
#include <drizzled/item/empty_string.h>
 
35
#include <drizzled/item/return_date_time.h>
 
36
#include <drizzled/sql_base.h>
 
37
#include <drizzled/db.h>
 
38
#include <drizzled/field/timestamp.h>
 
39
#include <drizzled/field/decimal.h>
 
40
#include <drizzled/lock.h>
 
41
#include <drizzled/item/return_date_time.h>
 
42
#include <drizzled/item/empty_string.h>
 
43
#include "drizzled/plugin_registry.h"
 
44
#include <drizzled/info_schema.h>
 
45
#include <drizzled/message/schema.pb.h>
39
46
 
40
47
#include <string>
41
48
#include <iostream>
45
52
 
46
53
using namespace std;
47
54
 
48
 
namespace drizzled
49
 
{
 
55
extern "C"
 
56
int show_var_cmp(const void *var1, const void *var2);
50
57
 
51
58
inline const char *
52
59
str_or_nil(const char *str)
54
61
  return str ? str : "<nil>";
55
62
}
56
63
 
57
 
int wild_case_compare(const charset_info_st * const cs, const char *str, const char *wildstr)
 
64
/* Match the values of enum ha_choice */
 
65
static const char *ha_choice_values[] = {"", "0", "1"};
 
66
 
 
67
static void store_key_options(String *packet, Table *table, KEY *key_info);
 
68
 
 
69
static vector<InfoSchemaTable *> all_schema_tables;
 
70
 
 
71
void add_infoschema_table(InfoSchemaTable *schema_table)
 
72
{
 
73
  if (schema_table->getFirstColumnIndex() == 0)
 
74
    schema_table->setFirstColumnIndex(-1);
 
75
  if (schema_table->getSecondColumnIndex() == 0)
 
76
   schema_table->setSecondColumnIndex(-1);
 
77
 
 
78
  all_schema_tables.push_back(schema_table);
 
79
}
 
80
 
 
81
void remove_infoschema_table(InfoSchemaTable *table)
 
82
{
 
83
  all_schema_tables.erase(remove_if(all_schema_tables.begin(),
 
84
                                    all_schema_tables.end(),
 
85
                                    bind2nd(equal_to<InfoSchemaTable *>(),
 
86
                                            table)),
 
87
                          all_schema_tables.end());
 
88
}
 
89
 
 
90
 
 
91
int wild_case_compare(const CHARSET_INFO * const cs, const char *str,const char *wildstr)
58
92
{
59
93
  register int flag;
60
 
 
61
94
  while (*wildstr)
62
95
  {
63
 
    while (*wildstr && *wildstr != internal::wild_many && *wildstr != internal::wild_one)
 
96
    while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
64
97
    {
65
 
      if (*wildstr == internal::wild_prefix && wildstr[1])
 
98
      if (*wildstr == wild_prefix && wildstr[1])
66
99
        wildstr++;
67
100
      if (my_toupper(cs, *wildstr++) != my_toupper(cs, *str++))
68
101
        return (1);
69
102
    }
70
103
    if (! *wildstr )
71
104
      return (*str != 0);
72
 
    if (*wildstr++ == internal::wild_one)
 
105
    if (*wildstr++ == wild_one)
73
106
    {
74
107
      if (! *str++)
75
108
        return (1);     /* One char; skip */
78
111
    {                                           /* Found '*' */
79
112
      if (! *wildstr)
80
113
        return (0);             /* '*' as last char: OK */
81
 
      flag=(*wildstr != internal::wild_many && *wildstr != internal::wild_one);
 
114
      flag=(*wildstr != wild_many && *wildstr != wild_one);
82
115
      do
83
116
      {
84
117
        if (flag)
85
118
        {
86
119
          char cmp;
87
 
          if ((cmp= *wildstr) == internal::wild_prefix && wildstr[1])
 
120
          if ((cmp= *wildstr) == wild_prefix && wildstr[1])
88
121
            cmp= wildstr[1];
89
122
          cmp= my_toupper(cs, cmp);
90
123
          while (*str && my_toupper(cs, *str) != cmp)
98
131
      return (1);
99
132
    }
100
133
  }
101
 
 
102
134
  return (*str != '\0');
103
135
}
104
136
 
 
137
/***************************************************************************
 
138
** List all table types supported
 
139
***************************************************************************/
 
140
 
 
141
 
 
142
/**
 
143
 * @brief
 
144
 *   Find files in a given directory.
 
145
 *
 
146
 * @param[in]  session    Thread handler
 
147
 * @param[out] files      Put found files in this list
 
148
 * @param[in]  db         Used in error message when directory is not found
 
149
 * @param[in]  path       Path to database
 
150
 * @param[in]  wild       Filter for found files
 
151
 * @param[in]  dir        Read databases in path if true, read .frm files in
 
152
 *                        database otherwise
 
153
 *
 
154
 * @retval FIND_FILES_OK    Success
 
155
 * @retval FIND_FILES_OOM   Out of memory error
 
156
 * @retval FIND_FILES_DIR   No such directory or directory can't be read
 
157
 */
 
158
find_files_result find_files(Session *session, vector<LEX_STRING*> &files,
 
159
                             const char *db, const char *path, const char *wild,
 
160
                             bool dir)
 
161
{
 
162
  if (wild && (wild[0] == '\0'))
 
163
    wild= 0;
 
164
 
 
165
  MY_DIR *dirp= my_dir(path, MYF(dir ? MY_WANT_STAT : 0));
 
166
  if (dirp == NULL)
 
167
  {
 
168
    if (my_errno == ENOENT)
 
169
      my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db);
 
170
    else
 
171
      my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
 
172
 
 
173
    return(FIND_FILES_DIR);
 
174
  }
 
175
 
 
176
  for (unsigned i= 0; i < dirp->number_off_files; i++)
 
177
  {
 
178
    uint32_t file_name_len;
 
179
    char uname[NAME_LEN + 1];                   /* Unencoded name */
 
180
    FILEINFO *file= dirp->dir_entry+i;
 
181
 
 
182
    if (dir)
 
183
    {                                           /* Return databases */
 
184
      if ((file->name[0] == '.' &&
 
185
          ((file->name[1] == '.' && file->name[2] == '\0') ||
 
186
            file->name[1] == '\0')))
 
187
        continue;                               /* . or .. */
 
188
 
 
189
      if (!S_ISDIR(file->mystat->st_mode))
 
190
        continue;
 
191
 
 
192
      file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
 
193
      if (wild && wild_compare(uname, wild, 0))
 
194
        continue;
 
195
    }
 
196
    else
 
197
    {
 
198
      // Return only .frm files which aren't temp files.
 
199
      char *ext= fn_rext(file->name);
 
200
      if (my_strcasecmp(system_charset_info, ext, ".dfe") ||
 
201
          is_prefix(file->name, TMP_FILE_PREFIX))
 
202
        continue;
 
203
 
 
204
      *ext= 0;
 
205
      file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
 
206
      if (wild)
 
207
      {
 
208
        if (wild_case_compare(files_charset_info, uname, wild))
 
209
          continue;
 
210
      }
 
211
    }
 
212
 
 
213
    LEX_STRING *file_name= 0;
 
214
    file_name= session->make_lex_string(file_name, uname, file_name_len, true);
 
215
    if (file_name == NULL)
 
216
    {
 
217
      my_dirend(dirp);
 
218
      return(FIND_FILES_OOM);
 
219
    }
 
220
 
 
221
    files.push_back(file_name);
 
222
  }
 
223
 
 
224
  my_dirend(dirp);
 
225
 
 
226
  return(FIND_FILES_OK);
 
227
}
 
228
 
 
229
 
 
230
bool drizzled_show_create(Session *session, TableList *table_list)
 
231
{
 
232
  Protocol *protocol= session->protocol;
 
233
  char buff[2048];
 
234
  String buffer(buff, sizeof(buff), system_charset_info);
 
235
 
 
236
  /* Only one table for now, but VIEW can involve several tables */
 
237
  if (session->open_normal_and_derived_tables(table_list, 0))
 
238
  {
 
239
    if (session->is_error())
 
240
      return true;
 
241
 
 
242
    /*
 
243
      Clear all messages with 'error' level status and
 
244
      issue a warning with 'warning' level status in
 
245
      case of invalid view and last error is ER_VIEW_INVALID
 
246
    */
 
247
    drizzle_reset_errors(session, true);
 
248
    session->clear_error();
 
249
  }
 
250
 
 
251
  buffer.length(0);
 
252
 
 
253
  if (store_create_info(table_list, &buffer, NULL))
 
254
    return true;
 
255
 
 
256
  List<Item> field_list;
 
257
  {
 
258
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
 
259
    // 1024 is for not to confuse old clients
 
260
    field_list.push_back(new Item_empty_string("Create Table",
 
261
                                               max(buffer.length(),(uint32_t)1024)));
 
262
  }
 
263
 
 
264
  if (protocol->sendFields(&field_list,
 
265
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
266
  {
 
267
    return true;
 
268
  }
 
269
  protocol->prepareForResend();
 
270
  {
 
271
    if (table_list->schema_table)
 
272
      protocol->store(table_list->schema_table->getTableName().c_str());
 
273
    else
 
274
      protocol->store(table_list->table->alias);
 
275
  }
 
276
 
 
277
  protocol->store(buffer.ptr(), buffer.length());
 
278
 
 
279
  if (protocol->write())
 
280
    return true;
 
281
 
 
282
  session->my_eof();
 
283
  return false;
 
284
}
 
285
 
 
286
/**
 
287
  Get a CREATE statement for a given database.
 
288
 
 
289
  The database is identified by its name, passed as @c dbname parameter.
 
290
  The name should be encoded using the system character set (UTF8 currently).
 
291
 
 
292
  Resulting statement is stored in the string pointed by @c buffer. The string
 
293
  is emptied first and its character set is set to the system character set.
 
294
 
 
295
  If HA_LEX_CREATE_IF_NOT_EXISTS flag is set in @c create_info->options, then
 
296
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
 
297
  in @c create_options are ignored.
 
298
 
 
299
  @param  session           The current thread instance.
 
300
  @param  dbname        The name of the database.
 
301
  @param  buffer        A String instance where the statement is stored.
 
302
  @param  create_info   If not NULL, the options member influences the resulting
 
303
                        CRATE statement.
 
304
 
 
305
  @returns true if errors are detected, false otherwise.
 
306
*/
 
307
 
 
308
static bool store_db_create_info(const char *dbname, String *buffer, bool if_not_exists)
 
309
{
 
310
  drizzled::message::Schema schema;
 
311
 
 
312
  if (!my_strcasecmp(system_charset_info, dbname,
 
313
                     INFORMATION_SCHEMA_NAME.c_str()))
 
314
  {
 
315
    dbname= INFORMATION_SCHEMA_NAME.c_str();
 
316
  }
 
317
  else
 
318
  {
 
319
    int r= get_database_metadata(dbname, &schema);
 
320
    if(r < 0)
 
321
      return true;
 
322
  }
 
323
 
 
324
  buffer->length(0);
 
325
  buffer->free();
 
326
  buffer->set_charset(system_charset_info);
 
327
  buffer->append(STRING_WITH_LEN("CREATE DATABASE "));
 
328
 
 
329
  if (if_not_exists)
 
330
    buffer->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
331
 
 
332
  buffer->append_identifier(dbname, strlen(dbname));
 
333
 
 
334
  if (schema.has_collation() && strcmp(schema.collation().c_str(),
 
335
                                       default_charset_info->name))
 
336
  {
 
337
    buffer->append(" COLLATE = ");
 
338
    buffer->append(schema.collation().c_str());
 
339
  }
 
340
 
 
341
  return false;
 
342
}
 
343
 
 
344
bool mysqld_show_create_db(Session *session, char *dbname, bool if_not_exists)
 
345
{
 
346
  char buff[2048];
 
347
  String buffer(buff, sizeof(buff), system_charset_info);
 
348
  Protocol *protocol=session->protocol;
 
349
 
 
350
  if (store_db_create_info(dbname, &buffer, if_not_exists))
 
351
  {
 
352
    /*
 
353
      This assumes that the only reason for which store_db_create_info()
 
354
      can fail is incorrect database name (which is the case now).
 
355
    */
 
356
    my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
 
357
    return true;
 
358
  }
 
359
 
 
360
  List<Item> field_list;
 
361
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
 
362
  field_list.push_back(new Item_empty_string("Create Database",1024));
 
363
 
 
364
  if (protocol->sendFields(&field_list,
 
365
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
366
    return true;
 
367
 
 
368
  protocol->prepareForResend();
 
369
  protocol->store(dbname, strlen(dbname));
 
370
  protocol->store(buffer.ptr(), buffer.length());
 
371
 
 
372
  if (protocol->write())
 
373
    return true;
 
374
  session->my_eof();
 
375
  return false;
 
376
}
 
377
 
 
378
 
 
379
 
 
380
/****************************************************************************
 
381
  Return only fields for API mysql_list_fields
 
382
  Use "show table wildcard" in mysql instead of this
 
383
****************************************************************************/
 
384
 
 
385
void
 
386
mysqld_list_fields(Session *session, TableList *table_list, const char *wild)
 
387
{
 
388
  Table *table;
 
389
 
 
390
  if (session->open_normal_and_derived_tables(table_list, 0))
 
391
    return;
 
392
  table= table_list->table;
 
393
 
 
394
  List<Item> field_list;
 
395
 
 
396
  Field **ptr,*field;
 
397
  for (ptr=table->field ; (field= *ptr); ptr++)
 
398
  {
 
399
    if (!wild || !wild[0] ||
 
400
        !wild_case_compare(system_charset_info, field->field_name,wild))
 
401
    {
 
402
      field_list.push_back(new Item_field(field));
 
403
    }
 
404
  }
 
405
  table->restoreRecordAsDefault();              // Get empty record
 
406
  table->use_all_columns();
 
407
  if (session->protocol->sendFields(&field_list, Protocol::SEND_DEFAULTS))
 
408
    return;
 
409
  session->my_eof();
 
410
}
 
411
 
 
412
 
105
413
/*
106
414
  Get the quote character for displaying an identifier.
107
415
 
127
435
  return '`';
128
436
}
129
437
 
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);
294
 
  return false;
295
 
}
296
 
 
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
 
} /* namespace drizzled */
 
438
 
 
439
/* Append directory name (if exists) to CREATE INFO */
 
440
 
 
441
static void append_directory(String *packet, const char *dir_type,
 
442
                             const char *filename)
 
443
{
 
444
  if (filename)
 
445
  {
 
446
    uint32_t length= dirname_length(filename);
 
447
    packet->append(' ');
 
448
    packet->append(dir_type);
 
449
    packet->append(STRING_WITH_LEN(" DIRECTORY='"));
 
450
    packet->append(filename, length);
 
451
    packet->append('\'');
 
452
  }
 
453
}
 
454
 
 
455
 
 
456
#define LIST_PROCESS_HOST_LEN 64
 
457
 
 
458
static bool get_field_default_value(Field *timestamp_field,
 
459
                                    Field *field, String *def_value,
 
460
                                    bool quoted)
 
461
{
 
462
  bool has_default;
 
463
  bool has_now_default;
 
464
 
 
465
  /*
 
466
     We are using CURRENT_TIMESTAMP instead of NOW because it is
 
467
     more standard
 
468
  */
 
469
  has_now_default= (timestamp_field == field &&
 
470
                    field->unireg_check != Field::TIMESTAMP_UN_FIELD);
 
471
 
 
472
  has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
 
473
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
 
474
                field->unireg_check != Field::NEXT_NUMBER);
 
475
 
 
476
  def_value->length(0);
 
477
  if (has_default)
 
478
  {
 
479
    if (has_now_default)
 
480
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
 
481
    else if (!field->is_null())
 
482
    {                                             // Not null by default
 
483
      char tmp[MAX_FIELD_WIDTH];
 
484
      String type(tmp, sizeof(tmp), field->charset());
 
485
      field->val_str(&type);
 
486
      if (type.length())
 
487
      {
 
488
        String def_val;
 
489
        uint32_t dummy_errors;
 
490
        /* convert to system_charset_info == utf8 */
 
491
        def_val.copy(type.ptr(), type.length(), field->charset(),
 
492
                     system_charset_info, &dummy_errors);
 
493
        if (quoted)
 
494
          append_unescaped(def_value, def_val.ptr(), def_val.length());
 
495
        else
 
496
          def_value->append(def_val.ptr(), def_val.length());
 
497
      }
 
498
      else if (quoted)
 
499
        def_value->append(STRING_WITH_LEN("''"));
 
500
    }
 
501
    else if (field->maybe_null() && quoted)
 
502
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
 
503
    else
 
504
      return false;
 
505
  }
 
506
  return has_default;
 
507
}
 
508
 
 
509
/*
 
510
  Build a CREATE TABLE statement for a table.
 
511
 
 
512
  SYNOPSIS
 
513
    store_create_info()
 
514
    table_list        A list containing one table to write statement
 
515
                      for.
 
516
    packet            Pointer to a string where statement will be
 
517
                      written.
 
518
    create_info_arg   Pointer to create information that can be used
 
519
                      to tailor the format of the statement.  Can be
 
520
                      NULL, in which case only SQL_MODE is considered
 
521
                      when building the statement.
 
522
 
 
523
  NOTE
 
524
    Currently always return 0, but might return error code in the
 
525
    future.
 
526
 
 
527
  RETURN
 
528
    0       OK
 
529
 */
 
530
 
 
531
int store_create_info(TableList *table_list, String *packet, HA_CREATE_INFO *create_info_arg)
 
532
{
 
533
  List<Item> field_list;
 
534
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
 
535
  const char *alias;
 
536
  string buff;
 
537
  String type(tmp, sizeof(tmp), system_charset_info);
 
538
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
 
539
  Field **ptr,*field;
 
540
  uint32_t primary_key;
 
541
  KEY *key_info;
 
542
  Table *table= table_list->table;
 
543
  handler *file= table->file;
 
544
  TableShare *share= table->s;
 
545
  HA_CREATE_INFO create_info;
 
546
  bool show_table_options= false;
 
547
  my_bitmap_map *old_map;
 
548
 
 
549
  table->restoreRecordAsDefault(); // Get empty record
 
550
 
 
551
  if (share->tmp_table)
 
552
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
 
553
  else
 
554
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
 
555
  if (create_info_arg &&
 
556
      (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
 
557
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
558
  if (table_list->schema_table)
 
559
    alias= table_list->schema_table->getTableName().c_str();
 
560
  else
 
561
    alias= share->table_name.str;
 
562
 
 
563
  packet->append_identifier(alias, strlen(alias));
 
564
  packet->append(STRING_WITH_LEN(" (\n"));
 
565
  /*
 
566
    We need this to get default values from the table
 
567
    We have to restore the read_set if we are called from insert in case
 
568
    of row based replication.
 
569
  */
 
570
  old_map= table->use_all_columns(table->read_set);
 
571
 
 
572
  for (ptr=table->field ; (field= *ptr); ptr++)
 
573
  {
 
574
    uint32_t flags = field->flags;
 
575
 
 
576
    if (ptr != table->field)
 
577
      packet->append(STRING_WITH_LEN(",\n"));
 
578
 
 
579
    packet->append(STRING_WITH_LEN("  "));
 
580
    packet->append_identifier(field->field_name, strlen(field->field_name));
 
581
    packet->append(' ');
 
582
    // check for surprises from the previous call to Field::sql_type()
 
583
    if (type.ptr() != tmp)
 
584
      type.set(tmp, sizeof(tmp), system_charset_info);
 
585
    else
 
586
      type.set_charset(system_charset_info);
 
587
 
 
588
    field->sql_type(type);
 
589
    packet->append(type.ptr(), type.length(), system_charset_info);
 
590
 
 
591
    if (field->has_charset())
 
592
    {
 
593
      if (field->charset() != share->table_charset)
 
594
      {
 
595
        packet->append(STRING_WITH_LEN(" CHARACTER SET "));
 
596
        packet->append(field->charset()->csname);
 
597
      }
 
598
 
 
599
      /*
 
600
        For string types dump collation name only if
 
601
        collation is not primary for the given charset
 
602
      */
 
603
      if (!(field->charset()->state & MY_CS_PRIMARY))
 
604
      {
 
605
        packet->append(STRING_WITH_LEN(" COLLATE "));
 
606
        packet->append(field->charset()->name);
 
607
      }
 
608
    }
 
609
 
 
610
    if (flags & NOT_NULL_FLAG)
 
611
      packet->append(STRING_WITH_LEN(" NOT NULL"));
 
612
    else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
613
    {
 
614
      /*
 
615
        TIMESTAMP field require explicit NULL flag, because unlike
 
616
        all other fields they are treated as NOT NULL by default.
 
617
      */
 
618
      packet->append(STRING_WITH_LEN(" NULL"));
 
619
    }
 
620
    {
 
621
      /*
 
622
        Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
 
623
        and about STORAGE (DISK or MEMORY).
 
624
      */
 
625
      enum column_format_type column_format= (enum column_format_type)
 
626
        ((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
627
      if (column_format)
 
628
      {
 
629
        packet->append(STRING_WITH_LEN(" /*!"));
 
630
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
 
631
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
 
632
          packet->append(STRING_WITH_LEN(" FIXED */"));
 
633
        else
 
634
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
 
635
      }
 
636
    }
 
637
    if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
 
638
    {
 
639
      packet->append(STRING_WITH_LEN(" DEFAULT "));
 
640
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
 
641
    }
 
642
 
 
643
    if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
644
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
 
645
 
 
646
    if (field->unireg_check == Field::NEXT_NUMBER)
 
647
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
 
648
 
 
649
    if (field->comment.length)
 
650
    {
 
651
      packet->append(STRING_WITH_LEN(" COMMENT "));
 
652
      append_unescaped(packet, field->comment.str, field->comment.length);
 
653
    }
 
654
  }
 
655
 
 
656
  key_info= table->key_info;
 
657
  memset(&create_info, 0, sizeof(create_info));
 
658
  /* Allow update_create_info to update row type */
 
659
  create_info.row_type= share->row_type;
 
660
  file->update_create_info(&create_info);
 
661
  primary_key= share->primary_key;
 
662
 
 
663
  for (uint32_t i=0 ; i < share->keys ; i++,key_info++)
 
664
  {
 
665
    KEY_PART_INFO *key_part= key_info->key_part;
 
666
    bool found_primary=0;
 
667
    packet->append(STRING_WITH_LEN(",\n  "));
 
668
 
 
669
    if (i == primary_key && is_primary_key(key_info))
 
670
    {
 
671
      found_primary=1;
 
672
      /*
 
673
        No space at end, because a space will be added after where the
 
674
        identifier would go, but that is not added for primary key.
 
675
      */
 
676
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
 
677
    }
 
678
    else if (key_info->flags & HA_NOSAME)
 
679
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
 
680
    else
 
681
      packet->append(STRING_WITH_LEN("KEY "));
 
682
 
 
683
    if (!found_primary)
 
684
     packet->append_identifier(key_info->name, strlen(key_info->name));
 
685
 
 
686
    packet->append(STRING_WITH_LEN(" ("));
 
687
 
 
688
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
689
    {
 
690
      if (j)
 
691
        packet->append(',');
 
692
 
 
693
      if (key_part->field)
 
694
        packet->append_identifier(key_part->field->field_name,
 
695
                                  strlen(key_part->field->field_name));
 
696
      if (key_part->field &&
 
697
          (key_part->length !=
 
698
           table->field[key_part->fieldnr-1]->key_length()))
 
699
      {
 
700
        buff.assign("(");
 
701
        buff.append(to_string((int32_t) key_part->length /
 
702
                              key_part->field->charset()->mbmaxlen));
 
703
        buff.append(")");
 
704
        packet->append(buff.c_str(), buff.length());
 
705
      }
 
706
    }
 
707
    packet->append(')');
 
708
    store_key_options(packet, table, key_info);
 
709
  }
 
710
 
 
711
  /*
 
712
    Get possible foreign key definitions stored in InnoDB and append them
 
713
    to the CREATE TABLE statement
 
714
  */
 
715
 
 
716
  if ((for_str= file->get_foreign_key_create_info()))
 
717
  {
 
718
    packet->append(for_str, strlen(for_str));
 
719
    file->free_foreign_key_create_info(for_str);
 
720
  }
 
721
 
 
722
  packet->append(STRING_WITH_LEN("\n)"));
 
723
  {
 
724
    show_table_options= true;
 
725
    /*
 
726
      Get possible table space definitions and append them
 
727
      to the CREATE TABLE statement
 
728
    */
 
729
 
 
730
    /*
 
731
      IF   check_create_info
 
732
      THEN add ENGINE only if it was used when creating the table
 
733
    */
 
734
    if (!create_info_arg ||
 
735
        (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
 
736
    {
 
737
      packet->append(STRING_WITH_LEN(" ENGINE="));
 
738
      packet->append(file->engine->getName().c_str());
 
739
    }
 
740
 
 
741
    /*
 
742
      Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
 
743
      and NEXT_ID > 1 (the default).  We must not print the clause
 
744
      for engines that do not support this as it would break the
 
745
      import of dumps, but as of this writing, the test for whether
 
746
      AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
 
747
      is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
 
748
      Because of that, we do not explicitly test for the feature,
 
749
      but may extrapolate its existence from that of an AUTO_INCREMENT column.
 
750
    */
 
751
 
 
752
    if (create_info.auto_increment_value > 1)
 
753
    {
 
754
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT="));
 
755
      buff= to_string(create_info.auto_increment_value);
 
756
      packet->append(buff.c_str(), buff.length());
 
757
    }
 
758
 
 
759
    if (share->min_rows)
 
760
    {
 
761
      packet->append(STRING_WITH_LEN(" MIN_ROWS="));
 
762
      buff= to_string(share->min_rows);
 
763
      packet->append(buff.c_str(), buff.length());
 
764
    }
 
765
 
 
766
    if (share->max_rows && !table_list->schema_table)
 
767
    {
 
768
      packet->append(STRING_WITH_LEN(" MAX_ROWS="));
 
769
      buff= to_string(share->max_rows);
 
770
      packet->append(buff.c_str(), buff.length());
 
771
    }
 
772
 
 
773
    if (share->avg_row_length)
 
774
    {
 
775
      packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
 
776
      buff= to_string(share->avg_row_length);
 
777
      packet->append(buff.c_str(), buff.length());
 
778
    }
 
779
 
 
780
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
 
781
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
 
782
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
 
783
      packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
 
784
    /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
 
785
    if (share->db_create_options & HA_OPTION_CHECKSUM)
 
786
      packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
 
787
    if (share->page_checksum != HA_CHOICE_UNDEF)
 
788
    {
 
789
      packet->append(STRING_WITH_LEN(" PAGE_CHECKSUM="));
 
790
      packet->append(ha_choice_values[(uint32_t) share->page_checksum], 1);
 
791
    }
 
792
    if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
 
793
      packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
 
794
    if (create_info.row_type != ROW_TYPE_DEFAULT)
 
795
    {
 
796
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
 
797
      packet->append(ha_row_type[(uint32_t) create_info.row_type]);
 
798
    }
 
799
    if (table->s->key_block_size)
 
800
    {
 
801
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
802
      buff= to_string(table->s->key_block_size);
 
803
      packet->append(buff.c_str(), buff.length());
 
804
    }
 
805
    if (share->block_size)
 
806
    {
 
807
      packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
 
808
      buff= to_string(share->block_size);
 
809
      packet->append(buff.c_str(), buff.length());
 
810
    }
 
811
    table->file->append_create_info(packet);
 
812
    if (share->comment.length)
 
813
    {
 
814
      packet->append(STRING_WITH_LEN(" COMMENT="));
 
815
      append_unescaped(packet, share->comment.str, share->comment.length);
 
816
    }
 
817
    if (share->connect_string.length)
 
818
    {
 
819
      packet->append(STRING_WITH_LEN(" CONNECTION="));
 
820
      append_unescaped(packet, share->connect_string.str, share->connect_string.length);
 
821
    }
 
822
    append_directory(packet, "DATA",  create_info.data_file_name);
 
823
    append_directory(packet, "INDEX", create_info.index_file_name);
 
824
  }
 
825
  table->restore_column_map(old_map);
 
826
  return(0);
 
827
}
 
828
 
 
829
static void store_key_options(String *packet, Table *table, KEY *key_info)
 
830
{
 
831
  char *end, buff[32];
 
832
 
 
833
  if (key_info->algorithm == HA_KEY_ALG_BTREE)
 
834
    packet->append(STRING_WITH_LEN(" USING BTREE"));
 
835
 
 
836
  if (key_info->algorithm == HA_KEY_ALG_HASH)
 
837
    packet->append(STRING_WITH_LEN(" USING HASH"));
 
838
 
 
839
  if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
 
840
      table->s->key_block_size != key_info->block_size)
 
841
  {
 
842
    packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
843
    end= int64_t10_to_str(key_info->block_size, buff, 10);
 
844
    packet->append(buff, (uint32_t) (end - buff));
 
845
  }
 
846
 
 
847
  assert(test(key_info->flags & HA_USES_COMMENT) ==
 
848
              (key_info->comment.length > 0));
 
849
  if (key_info->flags & HA_USES_COMMENT)
 
850
  {
 
851
    packet->append(STRING_WITH_LEN(" COMMENT "));
 
852
    append_unescaped(packet, key_info->comment.str,
 
853
                     key_info->comment.length);
 
854
  }
 
855
}
 
856
 
 
857
 
 
858
/****************************************************************************
 
859
  Return info about all processes
 
860
  returns for each thread: thread id, user, host, db, command, info
 
861
****************************************************************************/
 
862
 
 
863
class thread_info :public ilink {
 
864
public:
 
865
  static void *operator new(size_t size)
 
866
  {
 
867
    return (void*) sql_alloc((uint32_t) size);
 
868
  }
 
869
  static void operator delete(void *, size_t)
 
870
  { TRASH(ptr, size); }
 
871
 
 
872
  my_thread_id thread_id;
 
873
  time_t start_time;
 
874
  uint32_t   command;
 
875
  const char *user,*host,*db,*proc_info,*state_info;
 
876
  char *query;
 
877
};
 
878
 
 
879
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
880
template class I_List<thread_info>;
 
881
#endif
 
882
 
 
883
void mysqld_list_processes(Session *session,const char *user, bool)
 
884
{
 
885
  Item *field;
 
886
  List<Item> field_list;
 
887
  I_List<thread_info> thread_infos;
 
888
  Protocol *protocol= session->protocol;
 
889
 
 
890
  field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
891
  field_list.push_back(new Item_empty_string("User",16));
 
892
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
 
893
  field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
 
894
  field->maybe_null= true;
 
895
  field_list.push_back(new Item_empty_string("Command",16));
 
896
  field_list.push_back(new Item_return_int("Time",7, DRIZZLE_TYPE_LONG));
 
897
  field_list.push_back(field=new Item_empty_string("State",30));
 
898
  field->maybe_null= true;
 
899
  field_list.push_back(field=new Item_empty_string("Info", PROCESS_LIST_WIDTH));
 
900
  field->maybe_null= true;
 
901
  if (protocol->sendFields(&field_list,
 
902
                           Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
903
    return;
 
904
 
 
905
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
906
  if (!session->killed)
 
907
  {
 
908
    Session *tmp;
 
909
    for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
 
910
    {
 
911
      tmp= *it;
 
912
      Security_context *tmp_sctx= &tmp->security_ctx;
 
913
      struct st_my_thread_var *mysys_var;
 
914
      if (tmp->protocol->isConnected() && (!user || (tmp_sctx->user.c_str() && !strcmp(tmp_sctx->user.c_str(), user))))
 
915
      {
 
916
        thread_info *session_info= new thread_info;
 
917
 
 
918
        session_info->thread_id=tmp->thread_id;
 
919
        session_info->user= session->strdup(tmp_sctx->user.c_str() ? tmp_sctx->user.c_str() : "unauthenticated user");
 
920
        session_info->host= session->strdup(tmp_sctx->ip.c_str());
 
921
        if ((session_info->db=tmp->db))             // Safe test
 
922
          session_info->db=session->strdup(session_info->db);
 
923
        session_info->command=(int) tmp->command;
 
924
        if ((mysys_var= tmp->mysys_var))
 
925
          pthread_mutex_lock(&mysys_var->mutex);
 
926
 
 
927
        if (tmp->killed == Session::KILL_CONNECTION)
 
928
          session_info->proc_info= (char*) "Killed";
 
929
        else
 
930
          session_info->proc_info= command_name[session_info->command].str;
 
931
 
 
932
        session_info->state_info= (char*) (tmp->protocol->isWriting() ?
 
933
                                           "Writing to net" :
 
934
                                           tmp->protocol->isReading() ?
 
935
                                           (session_info->command == COM_SLEEP ?
 
936
                                            NULL : "Reading from net") :
 
937
                                       tmp->get_proc_info() ? tmp->get_proc_info() :
 
938
                                       tmp->mysys_var &&
 
939
                                       tmp->mysys_var->current_cond ?
 
940
                                       "Waiting on cond" : NULL);
 
941
        if (mysys_var)
 
942
          pthread_mutex_unlock(&mysys_var->mutex);
 
943
 
 
944
        session_info->start_time= tmp->start_time;
 
945
        session_info->query= NULL;
 
946
        if (tmp->process_list_info[0])
 
947
          session_info->query= session->strdup(tmp->process_list_info);
 
948
        thread_infos.append(session_info);
 
949
      }
 
950
    }
 
951
  }
 
952
  pthread_mutex_unlock(&LOCK_thread_count);
 
953
 
 
954
  thread_info *session_info;
 
955
  time_t now= time(NULL);
 
956
  while ((session_info=thread_infos.get()))
 
957
  {
 
958
    protocol->prepareForResend();
 
959
    protocol->store((uint64_t) session_info->thread_id);
 
960
    protocol->store(session_info->user);
 
961
    protocol->store(session_info->host);
 
962
    protocol->store(session_info->db);
 
963
    protocol->store(session_info->proc_info);
 
964
 
 
965
    if (session_info->start_time)
 
966
      protocol->store((uint32_t) (now - session_info->start_time));
 
967
    else
 
968
      protocol->store();
 
969
 
 
970
    protocol->store(session_info->state_info);
 
971
    protocol->store(session_info->query);
 
972
 
 
973
    if (protocol->write())
 
974
      break; /* purecov: inspected */
 
975
  }
 
976
  session->my_eof();
 
977
  return;
 
978
}
 
979
 
 
980
/*****************************************************************************
 
981
  Status functions
 
982
*****************************************************************************/
 
983
 
 
984
static vector<SHOW_VAR *> all_status_vars;
 
985
static bool status_vars_inited= 0;
 
986
int show_var_cmp(const void *var1, const void *var2)
 
987
{
 
988
  return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
 
989
}
 
990
 
 
991
class show_var_cmp_functor
 
992
{
 
993
  public:
 
994
  show_var_cmp_functor() { }
 
995
  inline bool operator()(const SHOW_VAR *var1, const SHOW_VAR *var2) const
 
996
  {
 
997
    int val= strcmp(var1->name, var2->name);
 
998
    return (val < 0);
 
999
  }
 
1000
};
 
1001
 
 
1002
class show_var_remove_if
 
1003
{
 
1004
  public:
 
1005
  show_var_remove_if() { }
 
1006
  inline bool operator()(const SHOW_VAR *curr) const
 
1007
  {
 
1008
    return (curr->type == SHOW_UNDEF);
 
1009
  }
 
1010
};
 
1011
 
 
1012
SHOW_VAR *getFrontOfStatusVars()
 
1013
{
 
1014
  return all_status_vars.front();
 
1015
}
 
1016
 
 
1017
/*
 
1018
  Adds an array of SHOW_VAR entries to the output of SHOW STATUS
 
1019
 
 
1020
  SYNOPSIS
 
1021
    add_status_vars(SHOW_VAR *list)
 
1022
    list - an array of SHOW_VAR entries to add to all_status_vars
 
1023
           the last entry must be {0,0,SHOW_UNDEF}
 
1024
 
 
1025
  NOTE
 
1026
    The handling of all_status_vars[] is completely internal, it's allocated
 
1027
    automatically when something is added to it, and deleted completely when
 
1028
    the last entry is removed.
 
1029
 
 
1030
    As a special optimization, if add_status_vars() is called before
 
1031
    init_status_vars(), it assumes "startup mode" - neither concurrent access
 
1032
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
 
1033
*/
 
1034
int add_status_vars(SHOW_VAR *list)
 
1035
{
 
1036
  int res= 0;
 
1037
  if (status_vars_inited)
 
1038
    pthread_mutex_lock(&LOCK_status);
 
1039
  while (list->name)
 
1040
    all_status_vars.insert(all_status_vars.begin(), list++);
 
1041
  if (status_vars_inited)
 
1042
    sort(all_status_vars.begin(), all_status_vars.end(),
 
1043
         show_var_cmp_functor());
 
1044
  if (status_vars_inited)
 
1045
    pthread_mutex_unlock(&LOCK_status);
 
1046
  return res;
 
1047
}
 
1048
 
 
1049
/*
 
1050
  Make all_status_vars[] usable for SHOW STATUS
 
1051
 
 
1052
  NOTE
 
1053
    See add_status_vars(). Before init_status_vars() call, add_status_vars()
 
1054
    works in a special fast "startup" mode. Thus init_status_vars()
 
1055
    should be called as late as possible but before enabling multi-threading.
 
1056
*/
 
1057
void init_status_vars()
 
1058
{
 
1059
  status_vars_inited= 1;
 
1060
  sort(all_status_vars.begin(), all_status_vars.end(),
 
1061
       show_var_cmp_functor());
 
1062
}
 
1063
 
 
1064
void reset_status_vars()
 
1065
{
 
1066
  vector<SHOW_VAR *>::iterator p= all_status_vars.begin();
 
1067
  while (p != all_status_vars.end())
 
1068
  {
 
1069
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
1070
    if ((*p)->type == SHOW_LONG)
 
1071
      (*p)->value= 0;
 
1072
    ++p;
 
1073
  }
 
1074
}
 
1075
 
 
1076
/*
 
1077
  catch-all cleanup function, cleans up everything no matter what
 
1078
 
 
1079
  DESCRIPTION
 
1080
    This function is not strictly required if all add_to_status/
 
1081
    remove_status_vars are properly paired, but it's a safety measure that
 
1082
    deletes everything from the all_status_vars vector even if some
 
1083
    remove_status_vars were forgotten
 
1084
*/
 
1085
void free_status_vars()
 
1086
{
 
1087
  all_status_vars.clear();
 
1088
}
 
1089
 
 
1090
/*
 
1091
  Removes an array of SHOW_VAR entries from the output of SHOW STATUS
 
1092
 
 
1093
  SYNOPSIS
 
1094
    remove_status_vars(SHOW_VAR *list)
 
1095
    list - an array of SHOW_VAR entries to remove to all_status_vars
 
1096
           the last entry must be {0,0,SHOW_UNDEF}
 
1097
 
 
1098
  NOTE
 
1099
    there's lots of room for optimizing this, especially in non-sorted mode,
 
1100
    but nobody cares - it may be called only in case of failed plugin
 
1101
    initialization in the mysqld startup.
 
1102
*/
 
1103
 
 
1104
void remove_status_vars(SHOW_VAR *list)
 
1105
{
 
1106
  if (status_vars_inited)
 
1107
  {
 
1108
    pthread_mutex_lock(&LOCK_status);
 
1109
    SHOW_VAR *all= all_status_vars.front();
 
1110
    int a= 0, b= all_status_vars.size(), c= (a+b)/2;
 
1111
 
 
1112
    for (; list->name; list++)
 
1113
    {
 
1114
      int res= 0;
 
1115
      for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
 
1116
      {
 
1117
        res= show_var_cmp(list, all+c);
 
1118
        if (res < 0)
 
1119
          b= c;
 
1120
        else if (res > 0)
 
1121
          a= c;
 
1122
        else
 
1123
          break;
 
1124
      }
 
1125
      if (res == 0)
 
1126
        all[c].type= SHOW_UNDEF;
 
1127
    }
 
1128
    /* removes all the SHOW_UNDEF elements from the vector */
 
1129
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
1130
                            all_status_vars.end(),show_var_remove_if()),
 
1131
                            all_status_vars.end());
 
1132
    pthread_mutex_unlock(&LOCK_status);
 
1133
  }
 
1134
  else
 
1135
  {
 
1136
    SHOW_VAR *all= all_status_vars.front();
 
1137
    uint32_t i;
 
1138
    for (; list->name; list++)
 
1139
    {
 
1140
      for (i= 0; i < all_status_vars.size(); i++)
 
1141
      {
 
1142
        if (show_var_cmp(list, all+i))
 
1143
          continue;
 
1144
        all[i].type= SHOW_UNDEF;
 
1145
        break;
 
1146
      }
 
1147
    }
 
1148
    /* removes all the SHOW_UNDEF elements from the vector */
 
1149
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
1150
                            all_status_vars.end(),show_var_remove_if()),
 
1151
                            all_status_vars.end());
 
1152
  }
 
1153
}
 
1154
 
 
1155
/* collect status for all running threads */
 
1156
 
 
1157
void calc_sum_of_all_status(STATUS_VAR *to)
 
1158
{
 
1159
  /* Ensure that thread id not killed during loop */
 
1160
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
1161
 
 
1162
  /* Get global values as base */
 
1163
  *to= global_status_var;
 
1164
 
 
1165
  /* Add to this status from existing threads */
 
1166
  for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
 
1167
  {
 
1168
    add_to_status(to, &((*it)->status_var));
 
1169
  }
 
1170
 
 
1171
  pthread_mutex_unlock(&LOCK_thread_count);
 
1172
  return;
 
1173
}
 
1174
 
 
1175
/*
 
1176
  Store record to I_S table, convert HEAP table
 
1177
  to MyISAM if necessary
 
1178
 
 
1179
  SYNOPSIS
 
1180
    schema_table_store_record()
 
1181
    session                   thread handler
 
1182
    table                 Information schema table to be updated
 
1183
 
 
1184
  RETURN
 
1185
    0                     success
 
1186
    1                     error
 
1187
*/
 
1188
 
 
1189
bool schema_table_store_record(Session *session, Table *table)
 
1190
{
 
1191
  int error;
 
1192
  if ((error= table->file->ha_write_row(table->record[0])))
 
1193
  {
 
1194
    Tmp_Table_Param *param= table->pos_in_table_list->schema_table_param;
 
1195
 
 
1196
    if (create_myisam_from_heap(session, table, param->start_recinfo,
 
1197
                                &param->recinfo, error, 0))
 
1198
      return true;
 
1199
  }
 
1200
  return false;
 
1201
}
 
1202
 
 
1203
 
 
1204
static int make_table_list(Session *session, Select_Lex *sel,
 
1205
                           LEX_STRING *db_name, LEX_STRING *table_name)
 
1206
{
 
1207
  Table_ident *table_ident;
 
1208
  table_ident= new Table_ident(session, *db_name, *table_name, 1);
 
1209
  sel->init_query();
 
1210
  if (!sel->add_table_to_list(session, table_ident, 0, 0, TL_READ))
 
1211
    return 1;
 
1212
  return 0;
 
1213
}
 
1214
 
 
1215
 
 
1216
/**
 
1217
  @brief    Get lookup value from the part of 'WHERE' condition
 
1218
 
 
1219
  @details This function gets lookup value from
 
1220
           the part of 'WHERE' condition if it's possible and
 
1221
           fill appropriate lookup_field_vals struct field
 
1222
           with this value.
 
1223
 
 
1224
  @param[in]      session                   thread handler
 
1225
  @param[in]      item_func             part of WHERE condition
 
1226
  @param[in]      table                 I_S table
 
1227
  @param[in, out] lookup_field_vals     Struct which holds lookup values
 
1228
 
 
1229
  @return
 
1230
    0             success
 
1231
    1             error, there can be no matching records for the condition
 
1232
*/
 
1233
 
 
1234
static bool get_lookup_value(Session *session, Item_func *item_func,
 
1235
                             TableList *table,
 
1236
                             LOOKUP_FIELD_VALUES *lookup_field_vals)
 
1237
{
 
1238
  InfoSchemaTable *schema_table= table->schema_table;
 
1239
  const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1240
    schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1241
  const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1242
    schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
 
1243
 
 
1244
  if (item_func->functype() == Item_func::EQ_FUNC ||
 
1245
      item_func->functype() == Item_func::EQUAL_FUNC)
 
1246
  {
 
1247
    int idx_field, idx_val;
 
1248
    char tmp[MAX_FIELD_WIDTH];
 
1249
    String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
 
1250
    Item_field *item_field;
 
1251
    const CHARSET_INFO * const cs= system_charset_info;
 
1252
 
 
1253
    if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
 
1254
        item_func->arguments()[1]->const_item())
 
1255
    {
 
1256
      idx_field= 0;
 
1257
      idx_val= 1;
 
1258
    }
 
1259
    else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
 
1260
             item_func->arguments()[0]->const_item())
 
1261
    {
 
1262
      idx_field= 1;
 
1263
      idx_val= 0;
 
1264
    }
 
1265
    else
 
1266
      return 0;
 
1267
 
 
1268
    item_field= (Item_field*) item_func->arguments()[idx_field];
 
1269
    if (table->table != item_field->field->table)
 
1270
      return 0;
 
1271
    tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
 
1272
 
 
1273
    /* impossible value */
 
1274
    if (!tmp_str)
 
1275
      return 1;
 
1276
 
 
1277
    /* Lookup value is database name */
 
1278
    if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
 
1279
                               (unsigned char *) item_field->field_name,
 
1280
                               strlen(item_field->field_name), 0))
 
1281
    {
 
1282
      session->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
 
1283
                           tmp_str->length(), false);
 
1284
    }
 
1285
    /* Lookup value is table name */
 
1286
    else if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name2,
 
1287
                                    strlen(field_name2),
 
1288
                                    (unsigned char *) item_field->field_name,
 
1289
                                    strlen(item_field->field_name), 0))
 
1290
    {
 
1291
      session->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
 
1292
                           tmp_str->length(), false);
 
1293
    }
 
1294
  }
 
1295
  return 0;
 
1296
}
 
1297
 
 
1298
 
 
1299
/**
 
1300
  @brief    Calculates lookup values from 'WHERE' condition
 
1301
 
 
1302
  @details This function calculates lookup value(database name, table name)
 
1303
           from 'WHERE' condition if it's possible and
 
1304
           fill lookup_field_vals struct fields with these values.
 
1305
 
 
1306
  @param[in]      session                   thread handler
 
1307
  @param[in]      cond                  WHERE condition
 
1308
  @param[in]      table                 I_S table
 
1309
  @param[in, out] lookup_field_vals     Struct which holds lookup values
 
1310
 
 
1311
  @return
 
1312
    0             success
 
1313
    1             error, there can be no matching records for the condition
 
1314
*/
 
1315
 
 
1316
bool calc_lookup_values_from_cond(Session *session, COND *cond, TableList *table,
 
1317
                                  LOOKUP_FIELD_VALUES *lookup_field_vals)
 
1318
{
 
1319
  if (!cond)
 
1320
    return 0;
 
1321
 
 
1322
  if (cond->type() == Item::COND_ITEM)
 
1323
  {
 
1324
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
1325
    {
 
1326
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1327
      Item *item;
 
1328
      while ((item= li++))
 
1329
      {
 
1330
        if (item->type() == Item::FUNC_ITEM)
 
1331
        {
 
1332
          if (get_lookup_value(session, (Item_func*)item, table, lookup_field_vals))
 
1333
            return 1;
 
1334
        }
 
1335
        else
 
1336
        {
 
1337
          if (calc_lookup_values_from_cond(session, item, table, lookup_field_vals))
 
1338
            return 1;
 
1339
        }
 
1340
      }
 
1341
    }
 
1342
    return 0;
 
1343
  }
 
1344
  else if (cond->type() == Item::FUNC_ITEM &&
 
1345
           get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals))
 
1346
    return 1;
 
1347
  return 0;
 
1348
}
 
1349
 
 
1350
 
 
1351
static bool uses_only_table_name_fields(Item *item, TableList *table)
 
1352
{
 
1353
  if (item->type() == Item::FUNC_ITEM)
 
1354
  {
 
1355
    Item_func *item_func= (Item_func*)item;
 
1356
    for (uint32_t i=0; i<item_func->argument_count(); i++)
 
1357
    {
 
1358
      if (!uses_only_table_name_fields(item_func->arguments()[i], table))
 
1359
        return 0;
 
1360
    }
 
1361
  }
 
1362
  else if (item->type() == Item::FIELD_ITEM)
 
1363
  {
 
1364
    Item_field *item_field= (Item_field*)item;
 
1365
    const CHARSET_INFO * const cs= system_charset_info;
 
1366
    InfoSchemaTable *schema_table= table->schema_table;
 
1367
    const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1368
      schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1369
    const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1370
      schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
 
1371
    if (table->table != item_field->field->table ||
 
1372
        (cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
 
1373
                               (unsigned char *) item_field->field_name,
 
1374
                               strlen(item_field->field_name), 0) &&
 
1375
         cs->coll->strnncollsp(cs, (unsigned char *) field_name2, strlen(field_name2),
 
1376
                               (unsigned char *) item_field->field_name,
 
1377
                               strlen(item_field->field_name), 0)))
 
1378
      return 0;
 
1379
  }
 
1380
  else if (item->type() == Item::REF_ITEM)
 
1381
    return uses_only_table_name_fields(item->real_item(), table);
 
1382
 
 
1383
  if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
 
1384
    return 0;
 
1385
 
 
1386
  return 1;
 
1387
}
 
1388
 
 
1389
 
 
1390
static COND * make_cond_for_info_schema(COND *cond, TableList *table)
 
1391
{
 
1392
  if (!cond)
 
1393
    return (COND*) 0;
 
1394
  if (cond->type() == Item::COND_ITEM)
 
1395
  {
 
1396
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
1397
    {
 
1398
      /* Create new top level AND item */
 
1399
      Item_cond_and *new_cond=new Item_cond_and;
 
1400
      if (!new_cond)
 
1401
        return (COND*) 0;
 
1402
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1403
      Item *item;
 
1404
      while ((item=li++))
 
1405
      {
 
1406
        Item *fix= make_cond_for_info_schema(item, table);
 
1407
        if (fix)
 
1408
          new_cond->argument_list()->push_back(fix);
 
1409
      }
 
1410
      switch (new_cond->argument_list()->elements) {
 
1411
      case 0:
 
1412
        return (COND*) 0;
 
1413
      case 1:
 
1414
        return new_cond->argument_list()->head();
 
1415
      default:
 
1416
        new_cond->quick_fix_field();
 
1417
        return new_cond;
 
1418
      }
 
1419
    }
 
1420
    else
 
1421
    {                                           // Or list
 
1422
      Item_cond_or *new_cond=new Item_cond_or;
 
1423
      if (!new_cond)
 
1424
        return (COND*) 0;
 
1425
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1426
      Item *item;
 
1427
      while ((item=li++))
 
1428
      {
 
1429
        Item *fix=make_cond_for_info_schema(item, table);
 
1430
        if (!fix)
 
1431
          return (COND*) 0;
 
1432
        new_cond->argument_list()->push_back(fix);
 
1433
      }
 
1434
      new_cond->quick_fix_field();
 
1435
      new_cond->top_level_item();
 
1436
      return new_cond;
 
1437
    }
 
1438
  }
 
1439
 
 
1440
  if (!uses_only_table_name_fields(cond, table))
 
1441
    return (COND*) 0;
 
1442
  return cond;
 
1443
}
 
1444
 
 
1445
 
 
1446
/**
 
1447
  @brief   Calculate lookup values(database name, table name)
 
1448
 
 
1449
  @details This function calculates lookup values(database name, table name)
 
1450
           from 'WHERE' condition or wild values (for 'SHOW' commands only)
 
1451
           from LEX struct and fill lookup_field_vals struct field
 
1452
           with these values.
 
1453
 
 
1454
  @param[in]      session                   thread handler
 
1455
  @param[in]      cond                  WHERE condition
 
1456
  @param[in]      tables                I_S table
 
1457
  @param[in, out] lookup_field_values   Struct which holds lookup values
 
1458
 
 
1459
  @return
 
1460
    0             success
 
1461
    1             error, there can be no matching records for the condition
 
1462
*/
 
1463
 
 
1464
bool get_lookup_field_values(Session *session, COND *cond, TableList *tables,
 
1465
                             LOOKUP_FIELD_VALUES *lookup_field_values)
 
1466
{
 
1467
  LEX *lex= session->lex;
 
1468
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
 
1469
  memset(lookup_field_values, 0, sizeof(LOOKUP_FIELD_VALUES));
 
1470
  switch (lex->sql_command) {
 
1471
  case SQLCOM_SHOW_DATABASES:
 
1472
    if (wild)
 
1473
    {
 
1474
      lookup_field_values->db_value.str= (char*) wild;
 
1475
      lookup_field_values->db_value.length= strlen(wild);
 
1476
      lookup_field_values->wild_db_value= 1;
 
1477
    }
 
1478
    return 0;
 
1479
  case SQLCOM_SHOW_TABLES:
 
1480
  case SQLCOM_SHOW_TABLE_STATUS:
 
1481
    lookup_field_values->db_value.str= lex->select_lex.db;
 
1482
    lookup_field_values->db_value.length=strlen(lex->select_lex.db);
 
1483
    if (wild)
 
1484
    {
 
1485
      lookup_field_values->table_value.str= (char*)wild;
 
1486
      lookup_field_values->table_value.length= strlen(wild);
 
1487
      lookup_field_values->wild_table_value= 1;
 
1488
    }
 
1489
    return 0;
 
1490
  default:
 
1491
    /*
 
1492
      The "default" is for queries over I_S.
 
1493
      All previous cases handle SHOW commands.
 
1494
    */
 
1495
    return calc_lookup_values_from_cond(session, cond, tables, lookup_field_values);
 
1496
  }
 
1497
}
 
1498
 
 
1499
 
 
1500
/**
 
1501
 * @brief
 
1502
 *   Create db names list. Information schema name always is first in list
 
1503
 *
 
1504
 * @param[in]  session          Thread handler
 
1505
 * @param[out] files            List of db names
 
1506
 * @param[in]  wild             Wild string
 
1507
 * @param[in]  idx_field_vals   idx_field_vals->db_name contains db name or
 
1508
 *                              wild string
 
1509
 * @param[out] with_i_schema    Returns 1 if we added 'IS' name to list
 
1510
 *                              otherwise returns 0
 
1511
 *
 
1512
 * @retval 0   Success
 
1513
 * @retval 1   Error
 
1514
 */
 
1515
int make_db_list(Session *session, vector<LEX_STRING*> &files,
 
1516
                 LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1517
                 bool *with_i_schema)
 
1518
{
 
1519
  LEX_STRING *i_s_name_copy= 0;
 
1520
  i_s_name_copy= session->make_lex_string(i_s_name_copy,
 
1521
                                      INFORMATION_SCHEMA_NAME.c_str(),
 
1522
                                      INFORMATION_SCHEMA_NAME.length(), true);
 
1523
  *with_i_schema= 0;
 
1524
  if (lookup_field_vals->wild_db_value)
 
1525
  {
 
1526
    /*
 
1527
      This part of code is only for SHOW DATABASES command.
 
1528
      idx_field_vals->db_value can be 0 when we don't use
 
1529
      LIKE clause (see also get_index_field_values() function)
 
1530
    */
 
1531
    if (!lookup_field_vals->db_value.str ||
 
1532
        !wild_case_compare(system_charset_info,
 
1533
                           INFORMATION_SCHEMA_NAME.c_str(),
 
1534
                           lookup_field_vals->db_value.str))
 
1535
    {
 
1536
      *with_i_schema= 1;
 
1537
      files.push_back(i_s_name_copy);
 
1538
    }
 
1539
    return (find_files(session, files, NULL, drizzle_data_home,
 
1540
                       lookup_field_vals->db_value.str, 1) != FIND_FILES_OK);
 
1541
  }
 
1542
 
 
1543
 
 
1544
  /*
 
1545
    If we have db lookup vaule we just add it to list and
 
1546
    exit from the function
 
1547
  */
 
1548
  if (lookup_field_vals->db_value.str)
 
1549
  {
 
1550
    if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.c_str(),
 
1551
                       lookup_field_vals->db_value.str))
 
1552
    {
 
1553
      *with_i_schema= 1;
 
1554
      files.push_back(i_s_name_copy);
 
1555
      return 0;
 
1556
    }
 
1557
 
 
1558
    files.push_back(&lookup_field_vals->db_value);
 
1559
    return 0;
 
1560
  }
 
1561
 
 
1562
  /*
 
1563
    Create list of existing databases. It is used in case
 
1564
    of select from information schema table
 
1565
  */
 
1566
  files.push_back(i_s_name_copy);
 
1567
 
 
1568
  *with_i_schema= 1;
 
1569
  return (find_files(session, files, NULL,
 
1570
                     drizzle_data_home, NULL, 1) != FIND_FILES_OK);
 
1571
}
 
1572
 
 
1573
 
 
1574
class AddSchemaTable : public unary_function<InfoSchemaTable *, bool>
 
1575
{
 
1576
  Session *session;
 
1577
  const char *wild;
 
1578
  vector<LEX_STRING*> &files;
 
1579
 
 
1580
public:
 
1581
  AddSchemaTable(Session *session_arg, vector<LEX_STRING*> &files_arg, const char *wild_arg)
 
1582
    : session(session_arg), wild(wild_arg), files(files_arg)
 
1583
  {}
 
1584
 
 
1585
  result_type operator() (argument_type schema_table)
 
1586
  {
 
1587
    if (schema_table->isHidden())
 
1588
    {
 
1589
      return false;
 
1590
    }
 
1591
 
 
1592
    const string &schema_table_name= schema_table->getTableName();
 
1593
 
 
1594
    if (wild && wild_case_compare(files_charset_info, schema_table_name.c_str(), wild))
 
1595
    {
 
1596
      return false;
 
1597
    }
 
1598
 
 
1599
    LEX_STRING *file_name= 0;
 
1600
    file_name= session->make_lex_string(file_name, schema_table_name.c_str(),
 
1601
                                        schema_table_name.length(), true);
 
1602
    if (file_name == NULL)
 
1603
    {
 
1604
      return true;
 
1605
    }
 
1606
 
 
1607
    files.push_back(file_name);
 
1608
    return false;
 
1609
  }
 
1610
};
 
1611
 
 
1612
 
 
1613
static int schema_tables_add(Session *session, vector<LEX_STRING*> &files, const char *wild)
 
1614
{
 
1615
  vector<InfoSchemaTable *>::iterator iter= find_if(all_schema_tables.begin(),
 
1616
                                                    all_schema_tables.end(),
 
1617
                                                    AddSchemaTable(session, files, wild));
 
1618
 
 
1619
  if (iter != all_schema_tables.end())
 
1620
  {
 
1621
    return 1;
 
1622
  }
 
1623
 
 
1624
  return 0;
 
1625
}
 
1626
 
 
1627
 
 
1628
/**
 
1629
  @brief          Create table names list
 
1630
 
 
1631
  @details        The function creates the list of table names in
 
1632
                  database
 
1633
 
 
1634
  @param[in]      session                   thread handler
 
1635
  @param[in]      table_names           List of table names in database
 
1636
  @param[in]      lex                   pointer to LEX struct
 
1637
  @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
 
1638
  @param[in]      with_i_schema         true means that we add I_S tables to list
 
1639
  @param[in]      db_name               database name
 
1640
 
 
1641
  @return         Operation status
 
1642
    @retval       0           ok
 
1643
    @retval       1           fatal error
 
1644
    @retval       2           Not fatal error; Safe to ignore this file list
 
1645
*/
 
1646
 
 
1647
static int
 
1648
make_table_name_list(Session *session, vector<LEX_STRING*> &table_names, LEX *lex,
 
1649
                     LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1650
                     bool with_i_schema, LEX_STRING *db_name)
 
1651
{
 
1652
  char path[FN_REFLEN];
 
1653
  build_table_filename(path, sizeof(path), db_name->str, "", false);
 
1654
  if (!lookup_field_vals->wild_table_value &&
 
1655
      lookup_field_vals->table_value.str)
 
1656
  {
 
1657
    if (with_i_schema)
 
1658
    {
 
1659
      if (find_schema_table(lookup_field_vals->table_value.str))
 
1660
      {
 
1661
        table_names.push_back(&lookup_field_vals->table_value);
 
1662
      }
 
1663
    }
 
1664
    else
 
1665
    {
 
1666
      table_names.push_back(&lookup_field_vals->table_value);
 
1667
    }
 
1668
    return 0;
 
1669
  }
 
1670
 
 
1671
  /*
 
1672
    This call will add all matching the wildcards (if specified) IS tables
 
1673
    to the list
 
1674
  */
 
1675
  if (with_i_schema)
 
1676
    return (schema_tables_add(session, table_names,
 
1677
                              lookup_field_vals->table_value.str));
 
1678
 
 
1679
  string db(db_name->str);
 
1680
 
 
1681
  TableNameIterator tniter(db);
 
1682
  int err= 0;
 
1683
  string table_name;
 
1684
 
 
1685
  do {
 
1686
    err= tniter.next(&table_name);
 
1687
 
 
1688
    if (err == 0)
 
1689
    {
 
1690
      LEX_STRING *file_name= NULL;
 
1691
      file_name= session->make_lex_string(file_name, table_name.c_str(),
 
1692
                                          table_name.length(), true);
 
1693
      const char* wild= lookup_field_vals->table_value.str;
 
1694
      if (wild && wild_compare(table_name.c_str(), wild, 0))
 
1695
        continue;
 
1696
      table_names.push_back(file_name);
 
1697
    }
 
1698
 
 
1699
  } while (err == 0);
 
1700
 
 
1701
  if (err > 0)
 
1702
  {
 
1703
    /* who knows what this error condition really does...
 
1704
       anyway, we're keeping behaviour from days of yore */
 
1705
    if (lex->sql_command != SQLCOM_SELECT)
 
1706
      return 1;
 
1707
    session->clear_error();
 
1708
    return 2;
 
1709
  }
 
1710
 
 
1711
  return 0;
 
1712
}
 
1713
 
 
1714
 
 
1715
/**
 
1716
  @brief          Fill I_S table for SHOW COLUMNS|INDEX commands
 
1717
 
 
1718
  @param[in]      session                      thread handler
 
1719
  @param[in]      tables                   TableList for I_S table
 
1720
  @param[in]      schema_table             pointer to I_S structure
 
1721
  @param[in]      open_tables_state_backup pointer to Open_tables_state object
 
1722
                                           which is used to save|restore original
 
1723
                                           status of variables related to
 
1724
                                           open tables state
 
1725
 
 
1726
  @return         Operation status
 
1727
    @retval       0           success
 
1728
    @retval       1           error
 
1729
*/
 
1730
 
 
1731
static int
 
1732
fill_schema_show_cols_or_idxs(Session *session, TableList *tables,
 
1733
                              InfoSchemaTable *schema_table,
 
1734
                              Open_tables_state *open_tables_state_backup)
 
1735
{
 
1736
  LEX *lex= session->lex;
 
1737
  bool res;
 
1738
  LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
 
1739
  enum_sql_command save_sql_command= lex->sql_command;
 
1740
  TableList *show_table_list= (TableList*) tables->schema_select_lex->
 
1741
    table_list.first;
 
1742
  Table *table= tables->table;
 
1743
  int error= 1;
 
1744
 
 
1745
  lex->all_selects_list= tables->schema_select_lex;
 
1746
  /*
 
1747
    Restore session->temporary_tables to be able to process
 
1748
    temporary tables(only for 'show index' & 'show columns').
 
1749
    This should be changed when processing of temporary tables for
 
1750
    I_S tables will be done.
 
1751
  */
 
1752
  session->temporary_tables= open_tables_state_backup->temporary_tables;
 
1753
  /*
 
1754
    Let us set fake sql_command so views won't try to merge
 
1755
    themselves into main statement. If we don't do this,
 
1756
    SELECT * from information_schema.xxxx will cause problems.
 
1757
    SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
 
1758
  */
 
1759
  lex->sql_command= SQLCOM_SHOW_FIELDS;
 
1760
  res= session->open_normal_and_derived_tables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
 
1761
  lex->sql_command= save_sql_command;
 
1762
  /*
 
1763
    get_all_tables() returns 1 on failure and 0 on success thus
 
1764
    return only these and not the result code of ::process_table()
 
1765
 
 
1766
    We should use show_table_list->alias instead of
 
1767
    show_table_list->table_name because table_name
 
1768
    could be changed during opening of I_S tables. It's safe
 
1769
    to use alias because alias contains original table name
 
1770
    in this case(this part of code is used only for
 
1771
    'show columns' & 'show statistics' commands).
 
1772
  */
 
1773
   table_name= session->make_lex_string(&tmp_lex_string1, show_table_list->alias,
 
1774
                                    strlen(show_table_list->alias), false);
 
1775
   db_name= session->make_lex_string(&tmp_lex_string, show_table_list->db,
 
1776
                                 show_table_list->db_length, false);
 
1777
 
 
1778
 
 
1779
   table->setWriteSet();
 
1780
   error= test(schema_table->processTable(session, show_table_list,
 
1781
                                          table, res, db_name,
 
1782
                                          table_name));
 
1783
   session->temporary_tables= 0;
 
1784
   session->close_tables_for_reopen(&show_table_list);
 
1785
 
 
1786
   return(error);
 
1787
}
 
1788
 
 
1789
 
 
1790
/**
 
1791
  @brief          Fill I_S table for SHOW Table NAMES commands
 
1792
 
 
1793
  @param[in]      session                      thread handler
 
1794
  @param[in]      table                    Table struct for I_S table
 
1795
  @param[in]      db_name                  database name
 
1796
  @param[in]      table_name               table name
 
1797
  @param[in]      with_i_schema            I_S table if true
 
1798
 
 
1799
  @return         Operation status
 
1800
    @retval       0           success
 
1801
    @retval       1           error
 
1802
*/
 
1803
 
 
1804
static int fill_schema_table_names(Session *session, Table *table,
 
1805
                                   LEX_STRING *db_name, LEX_STRING *table_name,
 
1806
                                   bool with_i_schema)
 
1807
{
 
1808
  if (with_i_schema)
 
1809
  {
 
1810
    table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
 
1811
                           system_charset_info);
 
1812
  }
 
1813
  else
 
1814
  {
 
1815
    char path[FN_REFLEN];
 
1816
    (void) build_table_filename(path, sizeof(path), db_name->str,
 
1817
                                table_name->str, false);
 
1818
 
 
1819
      table->field[3]->store(STRING_WITH_LEN("BASE Table"),
 
1820
                             system_charset_info);
 
1821
 
 
1822
    if (session->is_error() && session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
1823
    {
 
1824
      session->clear_error();
 
1825
      return 0;
 
1826
    }
 
1827
  }
 
1828
  if (schema_table_store_record(session, table))
 
1829
    return 1;
 
1830
  return 0;
 
1831
}
 
1832
 
 
1833
 
 
1834
/**
 
1835
  @brief          Get open table method
 
1836
 
 
1837
  @details        The function calculates the method which will be used
 
1838
                  for table opening:
 
1839
                  SKIP_OPEN_TABLE - do not open table
 
1840
                  OPEN_FRM_ONLY   - open FRM file only
 
1841
                  OPEN_FULL_TABLE - open FRM, data, index files
 
1842
  @param[in]      tables               I_S table table_list
 
1843
  @param[in]      schema_table         I_S table struct
 
1844
 
 
1845
  @return         return a set of flags
 
1846
    @retval       SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
 
1847
*/
 
1848
 
 
1849
static uint32_t get_table_open_method(TableList *tables,
 
1850
                                      InfoSchemaTable *schema_table)
 
1851
{
 
1852
  /*
 
1853
    determine which method will be used for table opening
 
1854
  */
 
1855
  if (schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
 
1856
  {
 
1857
    Field **ptr, *field;
 
1858
    int table_open_method= 0, field_indx= 0;
 
1859
    for (ptr= tables->table->field; (field= *ptr) ; ptr++)
 
1860
    {
 
1861
      if (field->isReadSet())
 
1862
        table_open_method|= schema_table->getColumnOpenMethod(field_indx);
 
1863
      field_indx++;
 
1864
    }
 
1865
    return table_open_method;
 
1866
  }
 
1867
  /* I_S tables which use get_all_tables but can not be optimized */
 
1868
  return (uint32_t) OPEN_FULL_TABLE;
 
1869
}
 
1870
 
 
1871
 
 
1872
/**
 
1873
  @brief          Fill I_S table with data from FRM file only
 
1874
 
 
1875
  @param[in]      session                      thread handler
 
1876
  @param[in]      table                    Table struct for I_S table
 
1877
  @param[in]      schema_table             I_S table struct
 
1878
  @param[in]      db_name                  database name
 
1879
  @param[in]      table_name               table name
 
1880
 
 
1881
  @return         Operation status
 
1882
    @retval       0           Table is processed and we can continue
 
1883
                              with new table
 
1884
    @retval       1           It's view and we have to use
 
1885
                              open_tables function for this table
 
1886
*/
 
1887
 
 
1888
static int fill_schema_table_from_frm(Session *session,TableList *tables,
 
1889
                                      InfoSchemaTable *schema_table,
 
1890
                                      LEX_STRING *db_name,
 
1891
                                      LEX_STRING *table_name)
 
1892
{
 
1893
  Table *table= tables->table;
 
1894
  TableShare *share;
 
1895
  Table tbl;
 
1896
  TableList table_list;
 
1897
  uint32_t res= 0;
 
1898
  int error;
 
1899
  char key[MAX_DBKEY_LENGTH];
 
1900
  uint32_t key_length;
 
1901
 
 
1902
  memset(&tbl, 0, sizeof(Table));
 
1903
 
 
1904
  table_list.table_name= table_name->str;
 
1905
  table_list.db= db_name->str;
 
1906
 
 
1907
  key_length= table_list.create_table_def_key(key);
 
1908
  pthread_mutex_lock(&LOCK_open); /* Locking to get table share when filling schema table from FRM */
 
1909
  share= TableShare::getShare(session, &table_list, key, key_length, 0, &error);
 
1910
  if (!share)
 
1911
  {
 
1912
    res= 0;
 
1913
    goto err;
 
1914
  }
 
1915
 
 
1916
  {
 
1917
    tbl.s= share;
 
1918
    table_list.table= &tbl;
 
1919
    res= schema_table->processTable(session, &table_list, table,
 
1920
                                    res, db_name, table_name);
 
1921
  }
 
1922
  /* For the moment we just set everything to read */
 
1923
  table->setReadSet();
 
1924
 
 
1925
  TableShare::release(share);
 
1926
 
 
1927
err:
 
1928
  pthread_mutex_unlock(&LOCK_open);
 
1929
  session->clear_error();
 
1930
  return res;
 
1931
}
 
1932
 
 
1933
 
 
1934
 
 
1935
/**
 
1936
  @brief          Fill I_S tables whose data are retrieved
 
1937
                  from frm files and storage engine
 
1938
 
 
1939
  @details        The information schema tables are internally represented as
 
1940
                  temporary tables that are filled at query execution time.
 
1941
                  Those I_S tables whose data are retrieved
 
1942
                  from frm files and storage engine are filled by the function
 
1943
                  InfoSchemaMethods::fillTable().
 
1944
 
 
1945
  @param[in]      session                      thread handler
 
1946
  @param[in]      tables                   I_S table
 
1947
  @param[in]      cond                     'WHERE' condition
 
1948
 
 
1949
  @return         Operation status
 
1950
    @retval       0                        success
 
1951
    @retval       1                        error
 
1952
*/
 
1953
int InfoSchemaMethods::fillTable(Session *session, TableList *tables, COND *cond)
 
1954
{
 
1955
  LEX *lex= session->lex;
 
1956
  Table *table= tables->table;
 
1957
  Select_Lex *old_all_select_lex= lex->all_selects_list;
 
1958
  enum_sql_command save_sql_command= lex->sql_command;
 
1959
  Select_Lex *lsel= tables->schema_select_lex;
 
1960
  InfoSchemaTable *schema_table= tables->schema_table;
 
1961
  Select_Lex sel;
 
1962
  LOOKUP_FIELD_VALUES lookup_field_vals;
 
1963
  bool with_i_schema;
 
1964
  vector<LEX_STRING*> db_names, table_names;
 
1965
  COND *partial_cond= 0;
 
1966
  uint32_t derived_tables= lex->derived_tables;
 
1967
  int error= 1;
 
1968
  Open_tables_state open_tables_state_backup;
 
1969
  Query_tables_list query_tables_list_backup;
 
1970
  uint32_t table_open_method;
 
1971
  bool old_value= session->no_warnings_for_error;
 
1972
 
 
1973
  /*
 
1974
    We should not introduce deadlocks even if we already have some
 
1975
    tables open and locked, since we won't lock tables which we will
 
1976
    open and will ignore possible name-locks for these tables.
 
1977
  */
 
1978
  session->reset_n_backup_open_tables_state(&open_tables_state_backup);
 
1979
 
 
1980
  tables->table_open_method= table_open_method=
 
1981
    get_table_open_method(tables, schema_table);
 
1982
  /*
 
1983
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
 
1984
    see sql_parse.cc, prepare_schema_table() function where
 
1985
    this values are initialized
 
1986
  */
 
1987
  if (lsel && lsel->table_list.first)
 
1988
  {
 
1989
    error= fill_schema_show_cols_or_idxs(session, tables, schema_table,
 
1990
                                         &open_tables_state_backup);
 
1991
    goto err;
 
1992
  }
 
1993
 
 
1994
  if (get_lookup_field_values(session, cond, tables, &lookup_field_vals))
 
1995
  {
 
1996
    error= 0;
 
1997
    goto err;
 
1998
  }
 
1999
 
 
2000
  if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
 
2001
  {
 
2002
    /*
 
2003
      if lookup value is empty string then
 
2004
      it's impossible table name or db name
 
2005
    */
 
2006
    if ((lookup_field_vals.db_value.str && !lookup_field_vals.db_value.str[0]) ||
 
2007
        (lookup_field_vals.table_value.str && !lookup_field_vals.table_value.str[0]))
 
2008
    {
 
2009
      error= 0;
 
2010
      goto err;
 
2011
    }
 
2012
  }
 
2013
 
 
2014
  if (lookup_field_vals.db_value.length &&
 
2015
      !lookup_field_vals.wild_db_value)
 
2016
    tables->has_db_lookup_value= true;
 
2017
 
 
2018
  if (lookup_field_vals.table_value.length &&
 
2019
      !lookup_field_vals.wild_table_value)
 
2020
    tables->has_table_lookup_value= true;
 
2021
 
 
2022
  if (tables->has_db_lookup_value && tables->has_table_lookup_value)
 
2023
    partial_cond= 0;
 
2024
  else
 
2025
    partial_cond= make_cond_for_info_schema(cond, tables);
 
2026
 
 
2027
  if (lex->describe)
 
2028
  {
 
2029
    /* EXPLAIN SELECT */
 
2030
    error= 0;
 
2031
    goto err;
 
2032
  }
 
2033
 
 
2034
  table->setWriteSet();
 
2035
  if (make_db_list(session, db_names, &lookup_field_vals, &with_i_schema))
 
2036
    goto err;
 
2037
 
 
2038
  for (vector<LEX_STRING*>::iterator db_name= db_names.begin(); db_name != db_names.end(); ++db_name )
 
2039
  {
 
2040
    session->no_warnings_for_error= 1;
 
2041
    table_names.clear();
 
2042
    int res= make_table_name_list(session, table_names, lex,
 
2043
                                  &lookup_field_vals,
 
2044
                                  with_i_schema, *db_name);
 
2045
 
 
2046
    if (res == 2)   /* Not fatal error, continue */
 
2047
      continue;
 
2048
 
 
2049
    if (res)
 
2050
      goto err;
 
2051
 
 
2052
    
 
2053
    for (vector<LEX_STRING*>::iterator table_name= table_names.begin(); table_name != table_names.end(); ++table_name)
 
2054
    {
 
2055
      table->restoreRecordAsDefault();
 
2056
      table->field[schema_table->getFirstColumnIndex()]->
 
2057
        store((*db_name)->str, (*db_name)->length, system_charset_info);
 
2058
      table->field[schema_table->getSecondColumnIndex()]->
 
2059
        store((*table_name)->str, (*table_name)->length, system_charset_info);
 
2060
 
 
2061
      if (!partial_cond || partial_cond->val_int())
 
2062
      {
 
2063
        /*
 
2064
          If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
 
2065
          we can skip table opening and we don't have lookup value for
 
2066
          table name or lookup value is wild string(table name list is
 
2067
          already created by make_table_name_list() function).
 
2068
        */
 
2069
        if (! table_open_method &&
 
2070
            schema_table->getTableName().compare("TABLES") == 0 &&
 
2071
            (! lookup_field_vals.table_value.length ||
 
2072
             lookup_field_vals.wild_table_value))
 
2073
        {
 
2074
          if (schema_table_store_record(session, table))
 
2075
            goto err;      /* Out of space in temporary table */
 
2076
          continue;
 
2077
        }
 
2078
 
 
2079
        /* SHOW Table NAMES command */
 
2080
        if (schema_table->getTableName().compare("TABLE_NAMES") == 0)
 
2081
        {
 
2082
          if (fill_schema_table_names(session, tables->table, *db_name,
 
2083
                                      *table_name, with_i_schema))
 
2084
            continue;
 
2085
        }
 
2086
        else
 
2087
        {
 
2088
          if (!(table_open_method & ~OPEN_FRM_ONLY) &&
 
2089
              !with_i_schema)
 
2090
          {
 
2091
            if (!fill_schema_table_from_frm(session, tables, schema_table, *db_name,
 
2092
                                            *table_name))
 
2093
              continue;
 
2094
          }
 
2095
 
 
2096
          LEX_STRING tmp_lex_string, orig_db_name;
 
2097
          /*
 
2098
            Set the parent lex of 'sel' because it is needed by
 
2099
            sel.init_query() which is called inside make_table_list.
 
2100
          */
 
2101
          session->no_warnings_for_error= 1;
 
2102
          sel.parent_lex= lex;
 
2103
          /* db_name can be changed in make_table_list() func */
 
2104
          if (!session->make_lex_string(&orig_db_name, (*db_name)->str,
 
2105
                                        (*db_name)->length, false))
 
2106
            goto err;
 
2107
 
 
2108
          if (make_table_list(session, &sel, *db_name, *table_name))
 
2109
            goto err;
 
2110
 
 
2111
          TableList *show_table_list= (TableList*) sel.table_list.first;
 
2112
          lex->all_selects_list= &sel;
 
2113
          lex->derived_tables= 0;
 
2114
          lex->sql_command= SQLCOM_SHOW_FIELDS;
 
2115
          show_table_list->i_s_requested_object=
 
2116
            schema_table->getRequestedObject();
 
2117
          res= session->open_normal_and_derived_tables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
 
2118
          lex->sql_command= save_sql_command;
 
2119
          /*
 
2120
            XXX->  show_table_list has a flag i_is_requested,
 
2121
            and when it's set, open_normal_and_derived_tables()
 
2122
            can return an error without setting an error message
 
2123
            in Session, which is a hack. This is why we have to
 
2124
            check for res, then for session->is_error() only then
 
2125
            for session->main_da.sql_errno().
 
2126
          */
 
2127
          if (res && session->is_error() &&
 
2128
              session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
2129
          {
 
2130
            /*
 
2131
              Hide error for not existing table.
 
2132
              This error can occur for example when we use
 
2133
              where condition with db name and table name and this
 
2134
              table does not exist.
 
2135
            */
 
2136
            res= 0;
 
2137
            session->clear_error();
 
2138
          }
 
2139
          else
 
2140
          {
 
2141
            /*
 
2142
              We should use show_table_list->alias instead of
 
2143
              show_table_list->table_name because table_name
 
2144
              could be changed during opening of I_S tables. It's safe
 
2145
              to use alias because alias contains original table name
 
2146
              in this case.
 
2147
            */
 
2148
            session->make_lex_string(&tmp_lex_string, show_table_list->alias,
 
2149
                                     strlen(show_table_list->alias), false);
 
2150
            res= schema_table->processTable(session, show_table_list, table,
 
2151
                                            res, &orig_db_name,
 
2152
                                            &tmp_lex_string);
 
2153
            session->close_tables_for_reopen(&show_table_list);
 
2154
          }
 
2155
          assert(!lex->query_tables_own_last);
 
2156
          if (res)
 
2157
            goto err;
 
2158
        }
 
2159
      }
 
2160
    }
 
2161
    /*
 
2162
      If we have information schema its always the first table and only
 
2163
      the first table. Reset for other tables.
 
2164
    */
 
2165
    with_i_schema= 0;
 
2166
  }
 
2167
 
 
2168
  error= 0;
 
2169
 
 
2170
err:
 
2171
  session->restore_backup_open_tables_state(&open_tables_state_backup);
 
2172
  lex->derived_tables= derived_tables;
 
2173
  lex->all_selects_list= old_all_select_lex;
 
2174
  lex->sql_command= save_sql_command;
 
2175
  session->no_warnings_for_error= old_value;
 
2176
  return(error);
 
2177
}
 
2178
 
 
2179
 
 
2180
/**
 
2181
  @brief    Store field characteristics into appropriate I_S table columns
 
2182
 
 
2183
  @param[in]      table             I_S table
 
2184
  @param[in]      field             processed field
 
2185
  @param[in]      cs                I_S table charset
 
2186
  @param[in]      offset            offset from beginning of table
 
2187
                                    to DATE_TYPE column in I_S table
 
2188
 
 
2189
  @return         void
 
2190
*/
 
2191
 
 
2192
static void store_column_type(Table *table, Field *field,
 
2193
                              const CHARSET_INFO * const cs,
 
2194
                              uint32_t offset)
 
2195
{
 
2196
  bool is_blob;
 
2197
  int decimals, field_length;
 
2198
  const char *tmp_buff;
 
2199
  char column_type_buff[MAX_FIELD_WIDTH];
 
2200
  String column_type(column_type_buff, sizeof(column_type_buff), cs);
 
2201
 
 
2202
  field->sql_type(column_type);
 
2203
  /* DTD_IDENTIFIER column */
 
2204
  table->field[offset + 7]->store(column_type.ptr(), column_type.length(), cs);
 
2205
  table->field[offset + 7]->set_notnull();
 
2206
  tmp_buff= strchr(column_type.ptr(), '(');
 
2207
  /* DATA_TYPE column */
 
2208
  table->field[offset]->store(column_type.ptr(),
 
2209
                         (tmp_buff ? tmp_buff - column_type.ptr() :
 
2210
                          column_type.length()), cs);
 
2211
  is_blob= (field->type() == DRIZZLE_TYPE_BLOB);
 
2212
  if (field->has_charset() || is_blob ||
 
2213
      field->real_type() == DRIZZLE_TYPE_VARCHAR)  // For varbinary type
 
2214
  {
 
2215
    uint32_t octet_max_length= field->max_display_length();
 
2216
    if (is_blob && octet_max_length != (uint32_t) 4294967295U)
 
2217
      octet_max_length /= field->charset()->mbmaxlen;
 
2218
    int64_t char_max_len= is_blob ?
 
2219
      (int64_t) octet_max_length / field->charset()->mbminlen :
 
2220
      (int64_t) octet_max_length / field->charset()->mbmaxlen;
 
2221
    /* CHARACTER_MAXIMUM_LENGTH column*/
 
2222
    table->field[offset + 1]->store(char_max_len, true);
 
2223
    table->field[offset + 1]->set_notnull();
 
2224
    /* CHARACTER_OCTET_LENGTH column */
 
2225
    table->field[offset + 2]->store((int64_t) octet_max_length, true);
 
2226
    table->field[offset + 2]->set_notnull();
 
2227
  }
 
2228
 
 
2229
  /*
 
2230
    Calculate field_length and decimals.
 
2231
    They are set to -1 if they should not be set (we should return NULL)
 
2232
  */
 
2233
 
 
2234
  decimals= field->decimals();
 
2235
  switch (field->type()) {
 
2236
  case DRIZZLE_TYPE_NEWDECIMAL:
 
2237
    field_length= ((Field_new_decimal*) field)->precision;
 
2238
    break;
 
2239
  case DRIZZLE_TYPE_LONG:
 
2240
  case DRIZZLE_TYPE_LONGLONG:
 
2241
    field_length= field->max_display_length() - 1;
 
2242
    break;
 
2243
  case DRIZZLE_TYPE_DOUBLE:
 
2244
    field_length= field->field_length;
 
2245
    if (decimals == NOT_FIXED_DEC)
 
2246
      decimals= -1;                           // return NULL
 
2247
    break;
 
2248
  default:
 
2249
    field_length= decimals= -1;
 
2250
    break;
 
2251
  }
 
2252
 
 
2253
  /* NUMERIC_PRECISION column */
 
2254
  if (field_length >= 0)
 
2255
  {
 
2256
    table->field[offset + 3]->store((int64_t) field_length, true);
 
2257
    table->field[offset + 3]->set_notnull();
 
2258
  }
 
2259
  /* NUMERIC_SCALE column */
 
2260
  if (decimals >= 0)
 
2261
  {
 
2262
    table->field[offset + 4]->store((int64_t) decimals, true);
 
2263
    table->field[offset + 4]->set_notnull();
 
2264
  }
 
2265
  if (field->has_charset())
 
2266
  {
 
2267
    /* CHARACTER_SET_NAME column*/
 
2268
    tmp_buff= field->charset()->csname;
 
2269
    table->field[offset + 5]->store(tmp_buff, strlen(tmp_buff), cs);
 
2270
    table->field[offset + 5]->set_notnull();
 
2271
    /* COLLATION_NAME column */
 
2272
    tmp_buff= field->charset()->name;
 
2273
    table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs);
 
2274
    table->field[offset + 6]->set_notnull();
 
2275
  }
 
2276
}
 
2277
 
 
2278
 
 
2279
int InfoSchemaMethods::processTable(Session *session, TableList *tables,
 
2280
                                    Table *table, bool res,
 
2281
                                    LEX_STRING *db_name,
 
2282
                                    LEX_STRING *table_name) const
 
2283
{
 
2284
  LEX *lex= session->lex;
 
2285
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
 
2286
  const CHARSET_INFO * const cs= system_charset_info;
 
2287
  Table *show_table;
 
2288
  TableShare *show_table_share;
 
2289
  Field **ptr, *field, *timestamp_field;
 
2290
  int count;
 
2291
 
 
2292
  if (res)
 
2293
  {
 
2294
    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
 
2295
    {
 
2296
      /*
 
2297
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
 
2298
        rather than in SHOW COLUMNS
 
2299
      */
 
2300
      if (session->is_error())
 
2301
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2302
                     session->main_da.sql_errno(), session->main_da.message());
 
2303
      session->clear_error();
 
2304
      res= 0;
 
2305
    }
 
2306
    return(res);
 
2307
  }
 
2308
 
 
2309
  show_table= tables->table;
 
2310
  show_table_share= show_table->s;
 
2311
  count= 0;
 
2312
 
 
2313
  if (tables->schema_table)
 
2314
  {
 
2315
    ptr= show_table->field;
 
2316
    timestamp_field= show_table->timestamp_field;
 
2317
  }
 
2318
  else
 
2319
  {
 
2320
    ptr= show_table_share->field;
 
2321
    timestamp_field= show_table_share->timestamp_field;
 
2322
  }
 
2323
 
 
2324
  /* For the moment we just set everything to read */
 
2325
  if (!show_table->read_set)
 
2326
  {
 
2327
    bitmap_set_all(&show_table->def_read_set);
 
2328
    show_table->read_set= &show_table->def_read_set;
 
2329
  }
 
2330
  show_table->use_all_columns();               // Required for default
 
2331
 
 
2332
  for (; (field= *ptr) ; ptr++)
 
2333
  {
 
2334
    unsigned char *pos;
 
2335
    char tmp[MAX_FIELD_WIDTH];
 
2336
    String type(tmp,sizeof(tmp), system_charset_info);
 
2337
    char *end;
 
2338
 
 
2339
    /* to satisfy 'field->val_str' ASSERTs */
 
2340
    field->table= show_table;
 
2341
    show_table->in_use= session;
 
2342
 
 
2343
    if (wild && wild[0] &&
 
2344
        wild_case_compare(system_charset_info, field->field_name,wild))
 
2345
      continue;
 
2346
 
 
2347
    count++;
 
2348
    /* Get default row, with all NULL fields set to NULL */
 
2349
    table->restoreRecordAsDefault();
 
2350
 
 
2351
    table->field[1]->store(db_name->str, db_name->length, cs);
 
2352
    table->field[2]->store(table_name->str, table_name->length, cs);
 
2353
    table->field[3]->store(field->field_name, strlen(field->field_name),
 
2354
                           cs);
 
2355
    table->field[4]->store((int64_t) count, true);
 
2356
 
 
2357
    if (get_field_default_value(timestamp_field, field, &type, 0))
 
2358
    {
 
2359
      table->field[5]->store(type.ptr(), type.length(), cs);
 
2360
      table->field[5]->set_notnull();
 
2361
    }
 
2362
    pos=(unsigned char*) ((field->flags & NOT_NULL_FLAG) ?  "NO" : "YES");
 
2363
    table->field[6]->store((const char*) pos,
 
2364
                           strlen((const char*) pos), cs);
 
2365
    store_column_type(table, field, cs, 7);
 
2366
 
 
2367
    pos=(unsigned char*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
 
2368
                 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
 
2369
                 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
 
2370
    table->field[15]->store((const char*) pos,
 
2371
                            strlen((const char*) pos), cs);
 
2372
 
 
2373
    end= tmp;
 
2374
    if (field->unireg_check == Field::NEXT_NUMBER)
 
2375
      table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
 
2376
    if (timestamp_field == field &&
 
2377
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
2378
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
 
2379
                              cs);
 
2380
    table->field[18]->store(field->comment.str, field->comment.length, cs);
 
2381
    {
 
2382
      enum column_format_type column_format= (enum column_format_type)
 
2383
        ((field->flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
2384
      pos=(unsigned char*)"Default";
 
2385
      table->field[19]->store((const char*) pos,
 
2386
                              strlen((const char*) pos), cs);
 
2387
      pos=(unsigned char*)(column_format == COLUMN_FORMAT_TYPE_DEFAULT ? "Default" :
 
2388
                   column_format == COLUMN_FORMAT_TYPE_FIXED ? "Fixed" :
 
2389
                                                             "Dynamic");
 
2390
      table->field[20]->store((const char*) pos,
 
2391
                              strlen((const char*) pos), cs);
 
2392
    }
 
2393
    if (schema_table_store_record(session, table))
 
2394
      return(1);
 
2395
  }
 
2396
  return(0);
 
2397
}
 
2398
 
 
2399
 
 
2400
class FindSchemaTableByName : public unary_function<InfoSchemaTable *, bool>
 
2401
{
 
2402
  const char *table_name;
 
2403
public:
 
2404
  FindSchemaTableByName(const char *table_name_arg)
 
2405
    : table_name(table_name_arg) {}
 
2406
  result_type operator() (argument_type schema_table)
 
2407
  {
 
2408
    return ! my_strcasecmp(system_charset_info,
 
2409
                           schema_table->getTableName().c_str(),
 
2410
                           table_name);
 
2411
  }
 
2412
};
 
2413
 
 
2414
 
 
2415
/*
 
2416
  Find schema_tables elment by name
 
2417
 
 
2418
  SYNOPSIS
 
2419
    find_schema_table()
 
2420
    table_name          table name
 
2421
 
 
2422
  RETURN
 
2423
    0   table not found
 
2424
    #   pointer to 'schema_tables' element
 
2425
*/
 
2426
 
 
2427
InfoSchemaTable *find_schema_table(const char* table_name)
 
2428
{
 
2429
  vector<InfoSchemaTable *>::iterator iter= 
 
2430
    find_if(all_schema_tables.begin(), all_schema_tables.end(),
 
2431
            FindSchemaTableByName(table_name));
 
2432
  if (iter != all_schema_tables.end())
 
2433
  {
 
2434
    return *iter;
 
2435
  }
 
2436
 
 
2437
  return NULL;
 
2438
}
 
2439
 
 
2440
 
 
2441
Table *InfoSchemaMethods::createSchemaTable(Session *session, TableList *table_list)
 
2442
  const
 
2443
{
 
2444
  int field_count= 0;
 
2445
  Item *item;
 
2446
  Table *table;
 
2447
  List<Item> field_list;
 
2448
  const CHARSET_INFO * const cs= system_charset_info;
 
2449
  const InfoSchemaTable::Columns &columns= table_list->schema_table->getColumns();
 
2450
  InfoSchemaTable::Columns::const_iterator iter= columns.begin();
 
2451
 
 
2452
  while (iter != columns.end())
 
2453
  {
 
2454
    const ColumnInfo *column= *iter;
 
2455
    switch (column->getType()) {
 
2456
    case DRIZZLE_TYPE_LONG:
 
2457
    case DRIZZLE_TYPE_LONGLONG:
 
2458
      if (!(item= new Item_return_int(column->getName().c_str(),
 
2459
                                      column->getLength(),
 
2460
                                      column->getType(),
 
2461
                                      column->getValue())))
 
2462
      {
 
2463
        return(0);
 
2464
      }
 
2465
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
 
2466
      break;
 
2467
    case DRIZZLE_TYPE_DATE:
 
2468
    case DRIZZLE_TYPE_TIMESTAMP:
 
2469
    case DRIZZLE_TYPE_DATETIME:
 
2470
      if (!(item=new Item_return_date_time(column->getName().c_str(),
 
2471
                                           column->getType())))
 
2472
      {
 
2473
        return(0);
 
2474
      }
 
2475
      break;
 
2476
    case DRIZZLE_TYPE_DOUBLE:
 
2477
      if ((item= new Item_float(column->getName().c_str(), 0.0, NOT_FIXED_DEC,
 
2478
                           column->getLength())) == NULL)
 
2479
        return NULL;
 
2480
      break;
 
2481
    case DRIZZLE_TYPE_NEWDECIMAL:
 
2482
      if (!(item= new Item_decimal((int64_t) column->getValue(), false)))
 
2483
      {
 
2484
        return(0);
 
2485
      }
 
2486
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
 
2487
      item->decimals= column->getLength() % 10;
 
2488
      item->max_length= (column->getLength()/100)%100;
 
2489
      if (item->unsigned_flag == 0)
 
2490
        item->max_length+= 1;
 
2491
      if (item->decimals > 0)
 
2492
        item->max_length+= 1;
 
2493
      item->set_name(column->getName().c_str(),
 
2494
                     column->getName().length(), cs);
 
2495
      break;
 
2496
    case DRIZZLE_TYPE_BLOB:
 
2497
      if (!(item= new Item_blob(column->getName().c_str(),
 
2498
                                column->getLength())))
 
2499
      {
 
2500
        return(0);
 
2501
      }
 
2502
      break;
 
2503
    default:
 
2504
      if (!(item= new Item_empty_string("", column->getLength(), cs)))
 
2505
      {
 
2506
        return(0);
 
2507
      }
 
2508
      item->set_name(column->getName().c_str(),
 
2509
                     column->getName().length(), cs);
 
2510
      break;
 
2511
    }
 
2512
    field_list.push_back(item);
 
2513
    item->maybe_null= (column->getFlags() & MY_I_S_MAYBE_NULL);
 
2514
    field_count++;
 
2515
    ++iter;
 
2516
  }
 
2517
  Tmp_Table_Param *tmp_table_param =
 
2518
    (Tmp_Table_Param*) (session->alloc(sizeof(Tmp_Table_Param)));
 
2519
  tmp_table_param->init();
 
2520
  tmp_table_param->table_charset= cs;
 
2521
  tmp_table_param->field_count= field_count;
 
2522
  tmp_table_param->schema_table= 1;
 
2523
  Select_Lex *select_lex= session->lex->current_select;
 
2524
  if (!(table= create_tmp_table(session, tmp_table_param,
 
2525
                                field_list, (order_st*) 0, 0, 0,
 
2526
                                (select_lex->options | session->options |
 
2527
                                 TMP_TABLE_ALL_COLUMNS),
 
2528
                                HA_POS_ERROR, table_list->alias)))
 
2529
    return(0);
 
2530
  my_bitmap_map* bitmaps=
 
2531
    (my_bitmap_map*) session->alloc(bitmap_buffer_size(field_count));
 
2532
  bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count);
 
2533
  table->read_set= &table->def_read_set;
 
2534
  bitmap_clear_all(table->read_set);
 
2535
  table_list->schema_table_param= tmp_table_param;
 
2536
  return(table);
 
2537
}
 
2538
 
 
2539
 
 
2540
/*
 
2541
  For old SHOW compatibility. It is used when
 
2542
  old SHOW doesn't have generated column names
 
2543
  Make list of fields for SHOW
 
2544
 
 
2545
  SYNOPSIS
 
2546
    InfoSchemaMethods::oldFormat()
 
2547
    session                     thread handler
 
2548
    schema_table        pointer to 'schema_tables' element
 
2549
 
 
2550
  RETURN
 
2551
   1    error
 
2552
   0    success
 
2553
*/
 
2554
 
 
2555
int InfoSchemaMethods::oldFormat(Session *session, InfoSchemaTable *schema_table)
 
2556
  const
 
2557
{
 
2558
  Name_resolution_context *context= &session->lex->select_lex.context;
 
2559
  const InfoSchemaTable::Columns columns= schema_table->getColumns();
 
2560
  InfoSchemaTable::Columns::const_iterator iter= columns.begin();
 
2561
 
 
2562
  while (iter != columns.end())
 
2563
  {
 
2564
    const ColumnInfo *column= *iter;
 
2565
    if (column->getOldName().length() != 0)
 
2566
    {
 
2567
      Item_field *field= new Item_field(context,
 
2568
                                        NULL, NULL,
 
2569
                                        column->getName().c_str());
 
2570
      if (field)
 
2571
      {
 
2572
        field->set_name(column->getOldName().c_str(),
 
2573
                        column->getOldName().length(),
 
2574
                        system_charset_info);
 
2575
        if (session->add_item_to_list(field))
 
2576
          return 1;
 
2577
      }
 
2578
    }
 
2579
    ++iter;
 
2580
  }
 
2581
  return 0;
 
2582
}
 
2583
 
 
2584
 
 
2585
/*
 
2586
  Create information_schema table
 
2587
 
 
2588
  SYNOPSIS
 
2589
  mysql_schema_table()
 
2590
    session                thread handler
 
2591
    lex                pointer to LEX
 
2592
    table_list         pointer to table_list
 
2593
 
 
2594
  RETURN
 
2595
    true on error
 
2596
*/
 
2597
 
 
2598
bool mysql_schema_table(Session *session, LEX *, TableList *table_list)
 
2599
{
 
2600
  Table *table;
 
2601
  if (!(table= table_list->schema_table->createSchemaTable(session, table_list)))
 
2602
    return true;
 
2603
  table->s->tmp_table= SYSTEM_TMP_TABLE;
 
2604
  /*
 
2605
    This test is necessary to make
 
2606
    case insensitive file systems +
 
2607
    upper case table names(information schema tables) +
 
2608
    views
 
2609
    working correctly
 
2610
  */
 
2611
  if (table_list->schema_table_name)
 
2612
    table->alias_name_used= my_strcasecmp(table_alias_charset,
 
2613
                                          table_list->schema_table_name,
 
2614
                                          table_list->alias);
 
2615
  table_list->table_name= table->s->table_name.str;
 
2616
  table_list->table_name_length= table->s->table_name.length;
 
2617
  table_list->table= table;
 
2618
  table->next= session->derived_tables;
 
2619
  session->derived_tables= table;
 
2620
  table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
 
2621
 
 
2622
  return false;
 
2623
}
 
2624
 
 
2625
 
 
2626
/*
 
2627
  Generate select from information_schema table
 
2628
 
 
2629
  SYNOPSIS
 
2630
    make_schema_select()
 
2631
    session                  thread handler
 
2632
    sel                  pointer to Select_Lex
 
2633
    schema_table_name    name of 'schema_tables' element
 
2634
 
 
2635
  RETURN
 
2636
    true on error
 
2637
*/
 
2638
 
 
2639
bool make_schema_select(Session *session, Select_Lex *sel,
 
2640
                        const string& schema_table_name)
 
2641
{
 
2642
  InfoSchemaTable *schema_table= find_schema_table(schema_table_name.c_str());
 
2643
  LEX_STRING db, table;
 
2644
  /*
 
2645
     We have to make non const db_name & table_name
 
2646
     because of lower_case_table_names
 
2647
  */
 
2648
  session->make_lex_string(&db, INFORMATION_SCHEMA_NAME.c_str(),
 
2649
                       INFORMATION_SCHEMA_NAME.length(), 0);
 
2650
  session->make_lex_string(&table, schema_table->getTableName().c_str(),
 
2651
                           schema_table->getTableName().length(), 0);
 
2652
  if (schema_table->oldFormat(session, schema_table) ||   /* Handle old syntax */
 
2653
      !sel->add_table_to_list(session, new Table_ident(session, db, table, 0),
 
2654
                              0, 0, TL_READ))
 
2655
  {
 
2656
    return true;
 
2657
  }
 
2658
  return false;
 
2659
}
 
2660
 
 
2661
 
 
2662
/*
 
2663
  Fill temporary schema tables before SELECT
 
2664
 
 
2665
  SYNOPSIS
 
2666
    get_schema_tables_result()
 
2667
    join  join which use schema tables
 
2668
    executed_place place where I_S table processed
 
2669
 
 
2670
  RETURN
 
2671
    false success
 
2672
    true  error
 
2673
*/
 
2674
 
 
2675
bool get_schema_tables_result(JOIN *join,
 
2676
                              enum enum_schema_table_state executed_place)
 
2677
{
 
2678
  JoinTable *tmp_join_tab= join->join_tab+join->tables;
 
2679
  Session *session= join->session;
 
2680
  LEX *lex= session->lex;
 
2681
  bool result= 0;
 
2682
 
 
2683
  session->no_warnings_for_error= 1;
 
2684
  for (JoinTable *tab= join->join_tab; tab < tmp_join_tab; tab++)
 
2685
  {
 
2686
    if (!tab->table || !tab->table->pos_in_table_list)
 
2687
      break;
 
2688
 
 
2689
    TableList *table_list= tab->table->pos_in_table_list;
 
2690
    if (table_list->schema_table)
 
2691
    {
 
2692
      bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
 
2693
                          lex->current_select->master_unit()->item);
 
2694
 
 
2695
 
 
2696
      /* skip I_S optimizations specific to get_all_tables */
 
2697
      if (session->lex->describe &&
 
2698
          (table_list->schema_table->isOptimizationPossible() != true))
 
2699
      {
 
2700
        continue;
 
2701
      }
 
2702
 
 
2703
      /*
 
2704
        If schema table is already processed and
 
2705
        the statement is not a subselect then
 
2706
        we don't need to fill this table again.
 
2707
        If schema table is already processed and
 
2708
        schema_table_state != executed_place then
 
2709
        table is already processed and
 
2710
        we should skip second data processing.
 
2711
      */
 
2712
      if (table_list->schema_table_state &&
 
2713
          (!is_subselect || table_list->schema_table_state != executed_place))
 
2714
        continue;
 
2715
 
 
2716
      /*
 
2717
        if table is used in a subselect and
 
2718
        table has been processed earlier with the same
 
2719
        'executed_place' value then we should refresh the table.
 
2720
      */
 
2721
      if (table_list->schema_table_state && is_subselect)
 
2722
      {
 
2723
        table_list->table->file->extra(HA_EXTRA_NO_CACHE);
 
2724
        table_list->table->file->extra(HA_EXTRA_RESET_STATE);
 
2725
        table_list->table->file->ha_delete_all_rows();
 
2726
        free_io_cache(table_list->table);
 
2727
        filesort_free_buffers(table_list->table,1);
 
2728
        table_list->table->null_row= 0;
 
2729
      }
 
2730
      else
 
2731
        table_list->table->file->stats.records= 0;
 
2732
 
 
2733
      if (table_list->schema_table->fillTable(session, table_list,
 
2734
                                               tab->select_cond))
 
2735
      {
 
2736
        result= 1;
 
2737
        join->error= 1;
 
2738
        tab->read_record.file= table_list->table->file;
 
2739
        table_list->schema_table_state= executed_place;
 
2740
        break;
 
2741
      }
 
2742
      tab->read_record.file= table_list->table->file;
 
2743
      table_list->schema_table_state= executed_place;
 
2744
    }
 
2745
  }
 
2746
  session->no_warnings_for_error= 0;
 
2747
  return(result);
 
2748
}