~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Jay Pipes
  • Date: 2009-09-15 21:01:42 UTC
  • mto: (1126.2.5 merge)
  • mto: This revision was merged to the branch mainline in revision 1128.
  • Revision ID: jpipes@serialcoder-20090915210142-x8mwiqn1q0vzjspp
Moves Alter_info out into its own header and source file, cleans up some related include mess in sql_lex.h, and renames Alter_info to AlterInfo.

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