~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

Fixed make update-po so that it doesn't change the .po files EVERY time distcheck is run. This one needs to go in to get us a good .po file baseline, and after that, the only changes to files  in .po dir will be specific changes driven by the actual changes in the actual source, rather than 100-bazillion lines which are comments about line numbers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
 
21
21
/* Function with list databases, tables or fields */
22
 
#include "config.h"
 
22
#include <drizzled/server_includes.h>
23
23
#include <drizzled/sql_select.h>
24
24
#include <drizzled/show.h>
25
25
#include <drizzled/gettext.h>
40
40
#include <drizzled/item/return_date_time.h>
41
41
#include <drizzled/item/empty_string.h>
42
42
#include "drizzled/plugin/registry.h"
43
 
#include "drizzled/session_list.h"
44
43
#include <drizzled/plugin/info_schema_table.h>
45
44
#include <drizzled/message/schema.pb.h>
46
45
#include <drizzled/plugin/client.h>
47
 
#include <drizzled/cached_directory.h>
48
 
#include "drizzled/sql_table.h"
49
 
#include "drizzled/global_charset_info.h"
50
 
#include "drizzled/pthread_globals.h"
51
 
#include "drizzled/internal/m_string.h"
52
 
#include "drizzled/internal/my_sys.h"
53
 
 
 
46
#include <mysys/cached_directory.h>
54
47
#include <sys/stat.h>
55
48
 
56
49
#include <string>
141
134
 
142
135
  if (directory.fail())
143
136
  {
144
 
    errno= directory.getError();
145
 
    my_error(ER_CANT_READ_DIR, MYF(0), path, errno);
 
137
    my_errno= directory.getError();
 
138
    my_error(ER_CANT_READ_DIR, MYF(0), path, my_errno);
146
139
 
147
140
    return true;
148
141
  }
165
158
 
166
159
    if (stat(entry->filename.c_str(), &entry_stat))
167
160
    {
168
 
      errno= errno;
169
 
      my_error(ER_CANT_GET_STAT, MYF(0), entry->filename.c_str(), errno);
 
161
      my_errno= errno;
 
162
      my_error(ER_CANT_GET_STAT, MYF(0), entry->filename.c_str(), my_errno);
170
163
      return(true);
171
164
    }
172
165
 
197
190
}
198
191
 
199
192
 
200
 
bool drizzled_show_create(Session *session, TableList *table_list, bool is_if_not_exists)
 
193
bool drizzled_show_create(Session *session, TableList *table_list)
201
194
{
202
195
  char buff[2048];
203
196
  String buffer(buff, sizeof(buff), system_charset_info);
219
212
 
220
213
  buffer.length(0);
221
214
 
222
 
  if (store_create_info(table_list, &buffer, is_if_not_exists))
 
215
  if (store_create_info(table_list, &buffer, NULL))
223
216
    return true;
224
217
 
225
218
  List<Item> field_list;
233
226
  if (session->client->sendFields(&field_list))
234
227
    return true;
235
228
  {
236
 
    session->client->store(table_list->table->alias);
 
229
    if (table_list->schema_table)
 
230
      session->client->store(table_list->schema_table->getTableName().c_str());
 
231
    else
 
232
      session->client->store(table_list->table->alias);
237
233
  }
238
234
 
239
235
  session->client->store(buffer.ptr(), buffer.length());
254
250
  Resulting statement is stored in the string pointed by @c buffer. The string
255
251
  is emptied first and its character set is set to the system character set.
256
252
 
257
 
  If is_if_not_exists is set, then
 
253
  If HA_LEX_CREATE_IF_NOT_EXISTS flag is set in @c create_info->options, then
258
254
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
259
255
  in @c create_options are ignored.
260
256
 
303
299
  return false;
304
300
}
305
301
 
306
 
bool mysqld_show_create_db(Session *session, const NormalisedDatabaseName &database_name, bool if_not_exists)
 
302
bool mysqld_show_create_db(Session *session, char *dbname, bool if_not_exists)
307
303
{
308
304
  char buff[2048];
309
305
  String buffer(buff, sizeof(buff), system_charset_info);
310
306
 
311
 
  if (store_db_create_info(database_name.to_string().c_str(), &buffer, if_not_exists))
 
307
  if (store_db_create_info(dbname, &buffer, if_not_exists))
312
308
  {
313
309
    /*
314
310
      This assumes that the only reason for which store_db_create_info()
315
311
      can fail is incorrect database name (which is the case now).
316
312
    */
317
 
    my_error(ER_BAD_DB_ERROR, MYF(0), database_name.to_string().c_str());
 
313
    my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
318
314
    return true;
319
315
  }
320
316
 
325
321
  if (session->client->sendFields(&field_list))
326
322
    return true;
327
323
 
328
 
  session->client->store(database_name.to_string().c_str(), database_name.to_string().length());
 
324
  session->client->store(dbname, strlen(dbname));
329
325
  session->client->store(buffer.ptr(), buffer.length());
330
326
 
331
327
  if (session->client->flush())
422
418
                      for.
423
419
    packet            Pointer to a string where statement will be
424
420
                      written.
 
421
    create_info_arg   Pointer to create information that can be used
 
422
                      to tailor the format of the statement.  Can be
 
423
                      NULL, in which case only SQL_MODE is considered
 
424
                      when building the statement.
425
425
 
426
426
  NOTE
427
427
    Currently always return 0, but might return error code in the
431
431
    0       OK
432
432
 */
433
433
 
434
 
int store_create_info(TableList *table_list, String *packet, bool is_if_not_exists)
 
434
int store_create_info(TableList *table_list, String *packet, HA_CREATE_INFO *create_info_arg)
435
435
{
436
436
  List<Item> field_list;
437
437
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
455
455
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
456
456
  else
457
457
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
458
 
  if (is_if_not_exists)
 
458
  if (create_info_arg &&
 
459
      (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
459
460
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
460
 
  alias= share->table_name.str;
 
461
  if (table_list->schema_table)
 
462
    alias= table_list->schema_table->getTableName().c_str();
 
463
  else
 
464
    alias= share->table_name.str;
461
465
 
462
466
  packet->append_identifier(alias, strlen(alias));
463
467
  packet->append(STRING_WITH_LEN(" (\n"));
626
630
      to the CREATE TABLE statement
627
631
    */
628
632
 
629
 
    /* 
630
 
      We should always store engine since we will now be 
631
 
      making sure engines accept options (aka... no
632
 
      dangling arguments for engines.
 
633
    /*
 
634
      IF   check_create_info
 
635
      THEN add ENGINE only if it was used when creating the table
633
636
    */
634
 
    packet->append(STRING_WITH_LEN(" ENGINE="));
635
 
    packet->append(cursor->engine->getName().c_str());
 
637
    if (!create_info_arg ||
 
638
        (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
 
639
    {
 
640
      packet->append(STRING_WITH_LEN(" ENGINE="));
 
641
      packet->append(cursor->engine->getName().c_str());
 
642
    }
636
643
 
637
644
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
638
645
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
701
708
  returns for each thread: thread id, user, host, db, command, info
702
709
****************************************************************************/
703
710
 
704
 
class thread_info
705
 
{
706
 
  thread_info();
 
711
class thread_info :public ilink {
707
712
public:
708
 
  uint64_t thread_id;
 
713
  static void *operator new(size_t size)
 
714
  {
 
715
    return (void*) sql_alloc((uint32_t) size);
 
716
  }
 
717
  static void operator delete(void *, size_t)
 
718
  { TRASH(ptr, size); }
 
719
 
 
720
  my_thread_id thread_id;
709
721
  time_t start_time;
710
722
  uint32_t   command;
711
 
  string user, host, db, proc_info, state_info, query;
712
 
  thread_info(uint64_t thread_id_arg,
713
 
              time_t start_time_arg,
714
 
              uint32_t command_arg,
715
 
              const string &user_arg,
716
 
              const string &host_arg,
717
 
              const string &db_arg,
718
 
              const string &proc_info_arg,
719
 
              const string &state_info_arg,
720
 
              const string &query_arg)
721
 
    : thread_id(thread_id_arg), start_time(start_time_arg), command(command_arg),
722
 
      user(user_arg), host(host_arg), db(db_arg), proc_info(proc_info_arg),
723
 
      state_info(state_info_arg), query(query_arg)
724
 
  {}
 
723
  const char *user,*host,*db,*proc_info,*state_info;
 
724
  char *query;
725
725
};
726
726
 
 
727
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
728
template class I_List<thread_info>;
 
729
#endif
 
730
 
727
731
void mysqld_list_processes(Session *session,const char *user, bool)
728
732
{
729
733
  Item *field;
730
734
  List<Item> field_list;
731
 
  vector<thread_info> thread_infos;
 
735
  I_List<thread_info> thread_infos;
732
736
 
733
737
  field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
734
738
  field_list.push_back(new Item_empty_string("User",16));
748
752
  if (!session->killed)
749
753
  {
750
754
    Session *tmp;
751
 
    for(vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it)
 
755
    for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
752
756
    {
753
757
      tmp= *it;
754
758
      Security_context *tmp_sctx= &tmp->security_ctx;
755
759
      struct st_my_thread_var *mysys_var;
756
760
      if (tmp->client->isConnected() && (!user || (tmp_sctx->user.c_str() && !strcmp(tmp_sctx->user.c_str(), user))))
757
761
      {
 
762
        thread_info *session_info= new thread_info;
758
763
 
 
764
        session_info->thread_id=tmp->thread_id;
 
765
        session_info->user= session->strdup(tmp_sctx->user.c_str() ? tmp_sctx->user.c_str() : "unauthenticated user");
 
766
        session_info->host= session->strdup(tmp_sctx->ip.c_str());
 
767
        if ((session_info->db= tmp->db.c_str()))             // Safe test
 
768
          session_info->db=session->strdup(session_info->db);
 
769
        session_info->command=(int) tmp->command;
759
770
        if ((mysys_var= tmp->mysys_var))
760
771
          pthread_mutex_lock(&mysys_var->mutex);
761
772
 
762
 
        const string tmp_proc_info((tmp->killed == Session::KILL_CONNECTION) ? "Killed" : command_name[tmp->command].str);
 
773
        if (tmp->killed == Session::KILL_CONNECTION)
 
774
          session_info->proc_info= (char*) "Killed";
 
775
        else
 
776
          session_info->proc_info= command_name[session_info->command].str;
763
777
 
764
 
        const string tmp_state_info(tmp->client->isWriting()
765
 
                                     ? "Writing to net"
766
 
                                     : tmp->client->isReading()
767
 
                                       ? (tmp->command == COM_SLEEP
768
 
                                            ? ""
769
 
                                            : "Reading from net")
770
 
                                       : tmp->get_proc_info()
771
 
                                         ? tmp->get_proc_info()
772
 
                                         : (tmp->mysys_var && tmp->mysys_var->current_cond)
773
 
                                           ? "Waiting on cond"
774
 
                                           : "");
 
778
        session_info->state_info= (char*) (tmp->client->isWriting() ?
 
779
                                           "Writing to net" :
 
780
                                           tmp->client->isReading() ?
 
781
                                           (session_info->command == COM_SLEEP ?
 
782
                                            NULL : "Reading from net") :
 
783
                                       tmp->get_proc_info() ? tmp->get_proc_info() :
 
784
                                       tmp->mysys_var &&
 
785
                                       tmp->mysys_var->current_cond ?
 
786
                                       "Waiting on cond" : NULL);
775
787
        if (mysys_var)
776
788
          pthread_mutex_unlock(&mysys_var->mutex);
777
789
 
778
 
        const string tmp_query((tmp->process_list_info[0]) ? tmp->process_list_info : "");
779
 
        thread_infos.push_back(thread_info(tmp->thread_id,
780
 
                                           tmp->start_time,
781
 
                                           tmp->command,
782
 
                                           tmp_sctx->user.empty()
783
 
                                             ? string("unauthenticated user")
784
 
                                             : tmp_sctx->user,
785
 
                                           tmp_sctx->ip,
786
 
                                           tmp->db,
787
 
                                           tmp_proc_info,
788
 
                                           tmp_state_info,
789
 
                                           tmp_query));
 
790
        session_info->start_time= tmp->start_time;
 
791
        session_info->query= NULL;
 
792
        if (tmp->process_list_info[0])
 
793
          session_info->query= session->strdup(tmp->process_list_info);
 
794
        thread_infos.append(session_info);
790
795
      }
791
796
    }
792
797
  }
793
798
  pthread_mutex_unlock(&LOCK_thread_count);
 
799
 
 
800
  thread_info *session_info;
794
801
  time_t now= time(NULL);
795
 
  for(vector<thread_info>::iterator iter= thread_infos.begin();
796
 
      iter != thread_infos.end();
797
 
      ++iter)
 
802
  while ((session_info=thread_infos.get()))
798
803
  {
799
 
    session->client->store((uint64_t) (*iter).thread_id);
800
 
    session->client->store((*iter).user);
801
 
    session->client->store((*iter).host);
802
 
    session->client->store((*iter).db);
803
 
    session->client->store((*iter).proc_info);
 
804
    session->client->store((uint64_t) session_info->thread_id);
 
805
    session->client->store(session_info->user);
 
806
    session->client->store(session_info->host);
 
807
    session->client->store(session_info->db);
 
808
    session->client->store(session_info->proc_info);
804
809
 
805
 
    if ((*iter).start_time)
806
 
      session->client->store((uint32_t) (now - (*iter).start_time));
 
810
    if (session_info->start_time)
 
811
      session->client->store((uint32_t) (now - session_info->start_time));
807
812
    else
808
813
      session->client->store();
809
814
 
810
 
    session->client->store((*iter).state_info);
811
 
    session->client->store((*iter).query);
 
815
    session->client->store(session_info->state_info);
 
816
    session->client->store(session_info->query);
812
817
 
813
818
    if (session->client->flush())
814
819
      break;
815
820
  }
816
821
  session->my_eof();
817
 
 
818
822
  return;
819
823
}
820
824
 
1004
1008
  *to= global_status_var;
1005
1009
 
1006
1010
  /* Add to this status from existing threads */
1007
 
  for(vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
1011
  for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
1008
1012
  {
1009
1013
    add_to_status(to, &((*it)->status_var));
1010
1014
  }
1013
1017
  return;
1014
1018
}
1015
1019
 
 
1020
/*
 
1021
  Store record to I_S table, convert HEAP table
 
1022
  to MyISAM if necessary
 
1023
 
 
1024
  SYNOPSIS
 
1025
    schema_table_store_record()
 
1026
    session                   thread Cursor
 
1027
    table                 Information schema table to be updated
 
1028
 
 
1029
  RETURN
 
1030
    0                     success
 
1031
    1                     error
 
1032
*/
 
1033
 
 
1034
bool schema_table_store_record(Session *session, Table *table)
 
1035
{
 
1036
  int error;
 
1037
  if ((error= table->cursor->ha_write_row(table->record[0])))
 
1038
  {
 
1039
    Tmp_Table_Param *param= table->pos_in_table_list->schema_table_param;
 
1040
 
 
1041
    if (create_myisam_from_heap(session, table, param->start_recinfo,
 
1042
                                &param->recinfo, error, 0))
 
1043
      return true;
 
1044
  }
 
1045
  return false;
 
1046
}
 
1047
 
1016
1048
 
1017
1049
static int make_table_list(Session *session, Select_Lex *sel,
1018
1050
                           LEX_STRING *db_name, LEX_STRING *table_name)
1046
1078
 
1047
1079
static bool get_lookup_value(Session *session, Item_func *item_func,
1048
1080
                             TableList *table,
1049
 
                             LOOKUP_FIELD_VALUES *lookup_field_vals,
1050
 
                             plugin::InfoSchemaTable *schema_table)
 
1081
                             LOOKUP_FIELD_VALUES *lookup_field_vals)
1051
1082
{
 
1083
  plugin::InfoSchemaTable *schema_table= table->schema_table;
1052
1084
  const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
1053
1085
    schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
1054
1086
  const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
1127
1159
*/
1128
1160
 
1129
1161
bool calc_lookup_values_from_cond(Session *session, COND *cond, TableList *table,
1130
 
                                  LOOKUP_FIELD_VALUES *lookup_field_vals,
1131
 
                                  plugin::InfoSchemaTable *schema_table)
 
1162
                                  LOOKUP_FIELD_VALUES *lookup_field_vals)
1132
1163
{
1133
1164
  if (!cond)
1134
1165
    return 0;
1143
1174
      {
1144
1175
        if (item->type() == Item::FUNC_ITEM)
1145
1176
        {
1146
 
          if (get_lookup_value(session, (Item_func*)item, table, lookup_field_vals, schema_table))
 
1177
          if (get_lookup_value(session, (Item_func*)item, table, lookup_field_vals))
1147
1178
            return 1;
1148
1179
        }
1149
1180
        else
1150
1181
        {
1151
 
          if (calc_lookup_values_from_cond(session, item, table, lookup_field_vals, schema_table))
 
1182
          if (calc_lookup_values_from_cond(session, item, table, lookup_field_vals))
1152
1183
            return 1;
1153
1184
        }
1154
1185
      }
1156
1187
    return 0;
1157
1188
  }
1158
1189
  else if (cond->type() == Item::FUNC_ITEM &&
1159
 
           get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals, schema_table))
 
1190
           get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals))
1160
1191
    return 1;
1161
1192
  return 0;
1162
1193
}
1163
1194
 
1164
1195
 
1165
 
static bool uses_only_table_name_fields(Item *item, Table *table, plugin::InfoSchemaTable *schema_table)
 
1196
static bool uses_only_table_name_fields(Item *item, TableList *table)
1166
1197
{
1167
1198
  if (item->type() == Item::FUNC_ITEM)
1168
1199
  {
1169
1200
    Item_func *item_func= (Item_func*)item;
1170
1201
    for (uint32_t i=0; i<item_func->argument_count(); i++)
1171
1202
    {
1172
 
      if (! uses_only_table_name_fields(item_func->arguments()[i], table, schema_table))
 
1203
      if (!uses_only_table_name_fields(item_func->arguments()[i], table))
1173
1204
        return 0;
1174
1205
    }
1175
1206
  }
1177
1208
  {
1178
1209
    Item_field *item_field= (Item_field*)item;
1179
1210
    const CHARSET_INFO * const cs= system_charset_info;
 
1211
    plugin::InfoSchemaTable *schema_table= table->schema_table;
1180
1212
    const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
1181
1213
      schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
1182
1214
    const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
1183
1215
      schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
1184
 
    if (table != item_field->field->table ||
 
1216
    if (table->table != item_field->field->table ||
1185
1217
        (cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
1186
1218
                               (unsigned char *) item_field->field_name,
1187
1219
                               strlen(item_field->field_name), 0) &&
1191
1223
      return 0;
1192
1224
  }
1193
1225
  else if (item->type() == Item::REF_ITEM)
1194
 
    return uses_only_table_name_fields(item->real_item(), table, schema_table);
 
1226
    return uses_only_table_name_fields(item->real_item(), table);
1195
1227
 
1196
1228
  if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
1197
1229
    return 0;
1200
1232
}
1201
1233
 
1202
1234
 
1203
 
static COND * make_cond_for_info_schema(COND *cond, Table *table, plugin::InfoSchemaTable *schema_table)
 
1235
static COND * make_cond_for_info_schema(COND *cond, TableList *table)
1204
1236
{
1205
1237
  if (!cond)
1206
1238
    return (COND*) 0;
1211
1243
      /* Create new top level AND item */
1212
1244
      Item_cond_and *new_cond=new Item_cond_and;
1213
1245
      if (!new_cond)
1214
 
        return (COND*) 0;
 
1246
        return (COND*) 0;
1215
1247
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1216
1248
      Item *item;
1217
1249
      while ((item=li++))
1218
1250
      {
1219
 
        Item *fix= make_cond_for_info_schema(item, table, schema_table);
1220
 
        if (fix)
1221
 
          new_cond->argument_list()->push_back(fix);
 
1251
        Item *fix= make_cond_for_info_schema(item, table);
 
1252
        if (fix)
 
1253
          new_cond->argument_list()->push_back(fix);
1222
1254
      }
1223
1255
      switch (new_cond->argument_list()->elements) {
1224
 
        case 0:
1225
 
          return (COND*) 0;
1226
 
        case 1:
1227
 
          return new_cond->argument_list()->head();
1228
 
        default:
1229
 
          new_cond->quick_fix_field();
1230
 
          return new_cond;
 
1256
      case 0:
 
1257
        return (COND*) 0;
 
1258
      case 1:
 
1259
        return new_cond->argument_list()->head();
 
1260
      default:
 
1261
        new_cond->quick_fix_field();
 
1262
        return new_cond;
1231
1263
      }
1232
1264
    }
1233
1265
    else
1234
1266
    {                                           // Or list
1235
1267
      Item_cond_or *new_cond=new Item_cond_or;
1236
1268
      if (!new_cond)
1237
 
        return (COND*) 0;
 
1269
        return (COND*) 0;
1238
1270
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1239
1271
      Item *item;
1240
1272
      while ((item=li++))
1241
1273
      {
1242
 
        Item *fix=make_cond_for_info_schema(item, table, schema_table);
1243
 
        if (!fix)
1244
 
          return (COND*) 0;
1245
 
        new_cond->argument_list()->push_back(fix);
 
1274
        Item *fix=make_cond_for_info_schema(item, table);
 
1275
        if (!fix)
 
1276
          return (COND*) 0;
 
1277
        new_cond->argument_list()->push_back(fix);
1246
1278
      }
1247
1279
      new_cond->quick_fix_field();
1248
1280
      new_cond->top_level_item();
1250
1282
    }
1251
1283
  }
1252
1284
 
1253
 
  if (! uses_only_table_name_fields(cond, table, schema_table))
 
1285
  if (!uses_only_table_name_fields(cond, table))
1254
1286
    return (COND*) 0;
1255
1287
  return cond;
1256
1288
}
1275
1307
*/
1276
1308
 
1277
1309
bool get_lookup_field_values(Session *session, COND *cond, TableList *tables,
1278
 
                             LOOKUP_FIELD_VALUES *lookup_field_values,
1279
 
                             plugin::InfoSchemaTable *schema_table)
 
1310
                             LOOKUP_FIELD_VALUES *lookup_field_values)
1280
1311
{
1281
1312
  LEX *lex= session->lex;
1282
1313
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
1306
1337
      The "default" is for queries over I_S.
1307
1338
      All previous cases handle SHOW commands.
1308
1339
    */
1309
 
    return calc_lookup_values_from_cond(session, cond, tables, lookup_field_values, schema_table);
 
1340
    return calc_lookup_values_from_cond(session, cond, tables, lookup_field_values);
1310
1341
  }
1311
1342
}
1312
1343
 
1576
1607
 
1577
1608
static int fill_schema_table_names(Session *session, Table *table,
1578
1609
                                   LEX_STRING *db_name, LEX_STRING *table_name,
1579
 
                                   bool with_i_schema,
1580
 
                                   plugin::InfoSchemaTable *schema_table)
 
1610
                                   bool with_i_schema)
1581
1611
{
1582
1612
  if (with_i_schema)
1583
1613
  {
1599
1629
      return 0;
1600
1630
    }
1601
1631
  }
1602
 
  schema_table->addRow(table->record[0], table->s->reclength);
 
1632
  if (schema_table_store_record(session, table))
 
1633
    return 1;
1603
1634
  return 0;
1604
1635
}
1605
1636
 
1606
 
int plugin::InfoSchemaMethods::fillTable(Session *session,
1607
 
                                         Table *table,
1608
 
                                         plugin::InfoSchemaTable *schema_table)
 
1637
 
 
1638
/**
 
1639
  @brief          Get open table method
 
1640
 
 
1641
  @details        The function calculates the method which will be used
 
1642
                  for table opening:
 
1643
                  SKIP_OPEN_TABLE - do not open table
 
1644
                  OPEN_FRM_ONLY   - open FRM cursor only
 
1645
                  OPEN_FULL_TABLE - open FRM, data, index files
 
1646
  @param[in]      tables               I_S table table_list
 
1647
  @param[in]      schema_table         I_S table struct
 
1648
 
 
1649
  @return         return a set of flags
 
1650
    @retval       SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
 
1651
*/
 
1652
 
 
1653
static uint32_t get_table_open_method(TableList *tables,
 
1654
                                      plugin::InfoSchemaTable *schema_table)
 
1655
{
 
1656
  /*
 
1657
    determine which method will be used for table opening
 
1658
  */
 
1659
  if (schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
 
1660
  {
 
1661
    Field **ptr, *field;
 
1662
    int table_open_method= 0, field_indx= 0;
 
1663
    for (ptr= tables->table->field; (field= *ptr) ; ptr++)
 
1664
    {
 
1665
      if (field->isReadSet())
 
1666
        table_open_method|= schema_table->getColumnOpenMethod(field_indx);
 
1667
      field_indx++;
 
1668
    }
 
1669
    return table_open_method;
 
1670
  }
 
1671
  /* I_S tables which use get_all_tables but can not be optimized */
 
1672
  return (uint32_t) OPEN_FULL_TABLE;
 
1673
}
 
1674
 
 
1675
 
 
1676
/**
 
1677
  @brief          Fill I_S table with data from FRM cursor only
 
1678
 
 
1679
  @param[in]      session                      thread Cursor
 
1680
  @param[in]      table                    Table struct for I_S table
 
1681
  @param[in]      schema_table             I_S table struct
 
1682
  @param[in]      db_name                  database name
 
1683
  @param[in]      table_name               table name
 
1684
 
 
1685
  @return         Operation status
 
1686
    @retval       0           Table is processed and we can continue
 
1687
                              with new table
 
1688
    @retval       1           It's view and we have to use
 
1689
                              open_tables function for this table
 
1690
*/
 
1691
 
 
1692
static int fill_schema_table_from_frm(Session *session,TableList *tables,
 
1693
                                      plugin::InfoSchemaTable *schema_table,
 
1694
                                      LEX_STRING *db_name,
 
1695
                                      LEX_STRING *table_name)
 
1696
{
 
1697
  Table *table= tables->table;
 
1698
  TableShare *share;
 
1699
  Table tbl;
 
1700
  TableList table_list;
 
1701
  uint32_t res= 0;
 
1702
  int error;
 
1703
  char key[MAX_DBKEY_LENGTH];
 
1704
  uint32_t key_length;
 
1705
 
 
1706
  memset(&tbl, 0, sizeof(Table));
 
1707
 
 
1708
  table_list.table_name= table_name->str;
 
1709
  table_list.db= db_name->str;
 
1710
 
 
1711
  key_length= table_list.create_table_def_key(key);
 
1712
  pthread_mutex_lock(&LOCK_open); /* Locking to get table share when filling schema table from FRM */
 
1713
  share= TableShare::getShare(session, &table_list, key, key_length, 0, &error);
 
1714
  if (!share)
 
1715
  {
 
1716
    res= 0;
 
1717
    goto err;
 
1718
  }
 
1719
 
 
1720
  {
 
1721
    tbl.s= share;
 
1722
    table_list.table= &tbl;
 
1723
    res= schema_table->processTable(session, &table_list, table,
 
1724
                                    res, db_name, table_name);
 
1725
  }
 
1726
  /* For the moment we just set everything to read */
 
1727
  table->setReadSet();
 
1728
 
 
1729
  TableShare::release(share);
 
1730
 
 
1731
err:
 
1732
  pthread_mutex_unlock(&LOCK_open);
 
1733
  session->clear_error();
 
1734
  return res;
 
1735
}
 
1736
 
 
1737
 
 
1738
 
 
1739
/**
 
1740
  @brief          Fill I_S tables whose data are retrieved
 
1741
                  from frm files and storage engine
 
1742
 
 
1743
  @details        The information schema tables are internally represented as
 
1744
                  temporary tables that are filled at query execution time.
 
1745
                  Those I_S tables whose data are retrieved
 
1746
                  from frm files and storage engine are filled by the function
 
1747
                  plugin::InfoSchemaMethods::fillTable().
 
1748
 
 
1749
  @param[in]      session                      thread Cursor
 
1750
  @param[in]      tables                   I_S table
 
1751
 
 
1752
  @return         Operation status
 
1753
    @retval       0                        success
 
1754
    @retval       1                        error
 
1755
*/
 
1756
int plugin::InfoSchemaMethods::fillTable(Session *session, TableList *tables)
1609
1757
{
1610
1758
  LEX *lex= session->lex;
 
1759
  Table *table= tables->table;
1611
1760
  Select_Lex *old_all_select_lex= lex->all_selects_list;
1612
1761
  enum_sql_command save_sql_command= lex->sql_command;
1613
 
  Select_Lex *lsel= table->pos_in_table_list->schema_select_lex;
 
1762
  Select_Lex *lsel= tables->schema_select_lex;
 
1763
  plugin::InfoSchemaTable *schema_table= tables->schema_table;
1614
1764
  Select_Lex sel;
1615
1765
  LOOKUP_FIELD_VALUES lookup_field_vals;
1616
1766
  bool with_i_schema;
1622
1772
  int error= 1;
1623
1773
  Open_tables_state open_tables_state_backup;
1624
1774
  Query_tables_list query_tables_list_backup;
 
1775
  uint32_t table_open_method;
1625
1776
  bool old_value= session->no_warnings_for_error;
1626
1777
 
1627
1778
  /*
1631
1782
  */
1632
1783
  session->reset_n_backup_open_tables_state(&open_tables_state_backup);
1633
1784
 
 
1785
  tables->table_open_method= table_open_method=
 
1786
    get_table_open_method(tables, schema_table);
1634
1787
  /*
1635
1788
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
1636
1789
    see sql_parse.cc, prepare_schema_table() function where
1638
1791
  */
1639
1792
  if (lsel && lsel->table_list.first)
1640
1793
  {
1641
 
    error= fill_schema_show_cols_or_idxs(session, table->pos_in_table_list, schema_table,
 
1794
    error= fill_schema_show_cols_or_idxs(session, tables, schema_table,
1642
1795
                                         &open_tables_state_backup);
1643
1796
    goto err;
1644
1797
  }
1645
1798
 
1646
 
  if (get_lookup_field_values(session, 
1647
 
                              cond, 
1648
 
                              table->pos_in_table_list, 
1649
 
                              &lookup_field_vals,
1650
 
                              schema_table))
 
1799
  if (get_lookup_field_values(session, cond, tables, &lookup_field_vals))
1651
1800
  {
1652
1801
    error= 0;
1653
1802
    goto err;
1669
1818
 
1670
1819
  if (lookup_field_vals.db_value.length &&
1671
1820
      !lookup_field_vals.wild_db_value)
1672
 
    table->pos_in_table_list->has_db_lookup_value= true;
 
1821
    tables->has_db_lookup_value= true;
1673
1822
 
1674
1823
  if (lookup_field_vals.table_value.length &&
1675
1824
      !lookup_field_vals.wild_table_value)
1676
 
    table->pos_in_table_list->has_table_lookup_value= true;
 
1825
    tables->has_table_lookup_value= true;
1677
1826
 
1678
 
  if (table->pos_in_table_list->has_db_lookup_value && 
1679
 
      table->pos_in_table_list->has_table_lookup_value)
 
1827
  if (tables->has_db_lookup_value && tables->has_table_lookup_value)
1680
1828
    partial_cond= 0;
1681
1829
  else
1682
 
    partial_cond= make_cond_for_info_schema(cond, table, schema_table);
 
1830
    partial_cond= make_cond_for_info_schema(cond, tables);
1683
1831
 
1684
1832
  if (lex->describe)
1685
1833
  {
1717
1865
 
1718
1866
      if (!partial_cond || partial_cond->val_int())
1719
1867
      {
 
1868
        /*
 
1869
          If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
 
1870
          we can skip table opening and we don't have lookup value for
 
1871
          table name or lookup value is wild string(table name list is
 
1872
          already created by make_table_name_list() function).
 
1873
        */
 
1874
        if (! table_open_method &&
 
1875
            schema_table->getTableName().compare("TABLES") == 0 &&
 
1876
            (! lookup_field_vals.table_value.length ||
 
1877
             lookup_field_vals.wild_table_value))
 
1878
        {
 
1879
          if (schema_table_store_record(session, table))
 
1880
            goto err;      /* Out of space in temporary table */
 
1881
          continue;
 
1882
        }
 
1883
 
1720
1884
        /* SHOW Table NAMES command */
1721
1885
        if (schema_table->getTableName().compare("TABLE_NAMES") == 0)
1722
1886
        {
1723
 
          if (fill_schema_table_names(session, 
1724
 
                                      table, 
1725
 
                                      *db_name,
1726
 
                                      *table_name, 
1727
 
                                      with_i_schema,
1728
 
                                      schema_table))
 
1887
          if (fill_schema_table_names(session, tables->table, *db_name,
 
1888
                                      *table_name, with_i_schema))
1729
1889
            continue;
1730
1890
        }
1731
1891
        else
1732
1892
        {
 
1893
          if (!(table_open_method & ~OPEN_FRM_ONLY) &&
 
1894
              !with_i_schema)
 
1895
          {
 
1896
            if (!fill_schema_table_from_frm(session, tables, schema_table, *db_name,
 
1897
                                            *table_name))
 
1898
              continue;
 
1899
          }
 
1900
 
1733
1901
          LEX_STRING tmp_lex_string, orig_db_name;
1734
1902
          /*
1735
1903
            Set the parent lex of 'sel' because it is needed by
1738
1906
          session->no_warnings_for_error= 1;
1739
1907
          sel.parent_lex= lex;
1740
1908
          /* db_name can be changed in make_table_list() func */
1741
 
          if (! session->make_lex_string(&orig_db_name, 
1742
 
                                         (*db_name)->str,
1743
 
                                         (*db_name)->length, 
1744
 
                                         false))
1745
 
          {
 
1909
          if (!session->make_lex_string(&orig_db_name, (*db_name)->str,
 
1910
                                        (*db_name)->length, false))
1746
1911
            goto err;
1747
 
          }
1748
1912
 
1749
1913
          if (make_table_list(session, &sel, *db_name, *table_name))
1750
1914
            goto err;
1917
2081
}
1918
2082
 
1919
2083
 
1920
 
int plugin::InfoSchemaMethods::processTable(
1921
 
            plugin::InfoSchemaTable *store_table,
1922
 
            Session *session, 
1923
 
            TableList *tables,
 
2084
int plugin::InfoSchemaMethods::processTable(Session *session, TableList *tables,
1924
2085
                                    Table *table, bool res,
1925
2086
                                    LEX_STRING *db_name,
1926
 
                                    LEX_STRING *table_name)
 
2087
                                    LEX_STRING *table_name) const
1927
2088
{
1928
2089
  LEX *lex= session->lex;
1929
2090
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
1954
2115
  show_table_share= show_table->s;
1955
2116
  count= 0;
1956
2117
 
1957
 
  ptr= show_table_share->field;
1958
 
  timestamp_field= show_table_share->timestamp_field;
 
2118
  if (tables->schema_table)
 
2119
  {
 
2120
    ptr= show_table->field;
 
2121
    timestamp_field= show_table->timestamp_field;
 
2122
  }
 
2123
  else
 
2124
  {
 
2125
    ptr= show_table_share->field;
 
2126
    timestamp_field= show_table_share->timestamp_field;
 
2127
  }
1959
2128
 
1960
2129
  /* For the moment we just set everything to read */
1961
2130
  if (!show_table->read_set)
2026
2195
      table->field[20]->store((const char*) pos,
2027
2196
                              strlen((const char*) pos), cs);
2028
2197
    }
2029
 
    store_table->addRow(table->record[0], table->s->reclength);
 
2198
    if (schema_table_store_record(session, table))
 
2199
      return(1);
2030
2200
  }
2031
2201
  return(0);
2032
2202
}
2033
2203
 
2034
2204
 
 
2205
Table *plugin::InfoSchemaMethods::createSchemaTable(Session *session, TableList *table_list)
 
2206
  const
 
2207
{
 
2208
  int field_count= 0;
 
2209
  Item *item;
 
2210
  Table *table;
 
2211
  List<Item> field_list;
 
2212
  const CHARSET_INFO * const cs= system_charset_info;
 
2213
  const plugin::InfoSchemaTable::Columns &columns= table_list->schema_table->getColumns();
 
2214
  plugin::InfoSchemaTable::Columns::const_iterator iter= columns.begin();
 
2215
 
 
2216
  while (iter != columns.end())
 
2217
  {
 
2218
    const plugin::ColumnInfo *column= *iter;
 
2219
    switch (column->getType()) {
 
2220
    case DRIZZLE_TYPE_LONG:
 
2221
    case DRIZZLE_TYPE_LONGLONG:
 
2222
      if (!(item= new Item_return_int(column->getName().c_str(),
 
2223
                                      column->getLength(),
 
2224
                                      column->getType(),
 
2225
                                      column->getValue())))
 
2226
      {
 
2227
        return(0);
 
2228
      }
 
2229
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
 
2230
      break;
 
2231
    case DRIZZLE_TYPE_DATE:
 
2232
    case DRIZZLE_TYPE_TIMESTAMP:
 
2233
    case DRIZZLE_TYPE_DATETIME:
 
2234
      if (!(item=new Item_return_date_time(column->getName().c_str(),
 
2235
                                           column->getType())))
 
2236
      {
 
2237
        return(0);
 
2238
      }
 
2239
      break;
 
2240
    case DRIZZLE_TYPE_DOUBLE:
 
2241
      if ((item= new Item_float(column->getName().c_str(), 0.0, NOT_FIXED_DEC,
 
2242
                           column->getLength())) == NULL)
 
2243
        return NULL;
 
2244
      break;
 
2245
    case DRIZZLE_TYPE_DECIMAL:
 
2246
      if (!(item= new Item_decimal((int64_t) column->getValue(), false)))
 
2247
      {
 
2248
        return(0);
 
2249
      }
 
2250
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
 
2251
      item->decimals= column->getLength() % 10;
 
2252
      item->max_length= (column->getLength()/100)%100;
 
2253
      if (item->unsigned_flag == 0)
 
2254
        item->max_length+= 1;
 
2255
      if (item->decimals > 0)
 
2256
        item->max_length+= 1;
 
2257
      item->set_name(column->getName().c_str(),
 
2258
                     column->getName().length(), cs);
 
2259
      break;
 
2260
    case DRIZZLE_TYPE_BLOB:
 
2261
      if (!(item= new Item_blob(column->getName().c_str(),
 
2262
                                column->getLength())))
 
2263
      {
 
2264
        return(0);
 
2265
      }
 
2266
      break;
 
2267
    default:
 
2268
      if (!(item= new Item_empty_string("", column->getLength(), cs)))
 
2269
      {
 
2270
        return(0);
 
2271
      }
 
2272
      item->set_name(column->getName().c_str(),
 
2273
                     column->getName().length(), cs);
 
2274
      break;
 
2275
    }
 
2276
    field_list.push_back(item);
 
2277
    item->maybe_null= (column->getFlags() & MY_I_S_MAYBE_NULL);
 
2278
    field_count++;
 
2279
    ++iter;
 
2280
  }
 
2281
  Tmp_Table_Param *tmp_table_param =
 
2282
    (Tmp_Table_Param*) (session->alloc(sizeof(Tmp_Table_Param)));
 
2283
  tmp_table_param->init();
 
2284
  tmp_table_param->table_charset= cs;
 
2285
  tmp_table_param->field_count= field_count;
 
2286
  tmp_table_param->schema_table= 1;
 
2287
  Select_Lex *select_lex= session->lex->current_select;
 
2288
  if (!(table= create_tmp_table(session, tmp_table_param,
 
2289
                                field_list, (order_st*) 0, 0, 0,
 
2290
                                (select_lex->options | session->options |
 
2291
                                 TMP_TABLE_ALL_COLUMNS),
 
2292
                                HA_POS_ERROR, table_list->alias)))
 
2293
    return(0);
 
2294
  my_bitmap_map* bitmaps=
 
2295
    (my_bitmap_map*) session->alloc(bitmap_buffer_size(field_count));
 
2296
  table->def_read_set.init((my_bitmap_map*) bitmaps, field_count);
 
2297
  table->read_set= &table->def_read_set;
 
2298
  table->read_set->clearAll();
 
2299
  table_list->schema_table_param= tmp_table_param;
 
2300
  return(table);
 
2301
}
 
2302
 
 
2303
 
2035
2304
/*
2036
2305
  For old SHOW compatibility. It is used when
2037
2306
  old SHOW doesn't have generated column names
2078
2347
 
2079
2348
 
2080
2349
/*
 
2350
  Create information_schema table
 
2351
 
 
2352
  SYNOPSIS
 
2353
  mysql_schema_table()
 
2354
    session                thread Cursor
 
2355
    lex                pointer to LEX
 
2356
    table_list         pointer to table_list
 
2357
 
 
2358
  RETURN
 
2359
    true on error
 
2360
*/
 
2361
 
 
2362
bool mysql_schema_table(Session *session, LEX *, TableList *table_list)
 
2363
{
 
2364
  Table *table;
 
2365
  if (!(table= table_list->schema_table->createSchemaTable(session, table_list)))
 
2366
    return true;
 
2367
  table->s->tmp_table= SYSTEM_TMP_TABLE;
 
2368
  /*
 
2369
    This test is necessary to make
 
2370
    case insensitive cursor systems +
 
2371
    upper case table names(information schema tables) +
 
2372
    views
 
2373
    working correctly
 
2374
  */
 
2375
  if (table_list->schema_table_name)
 
2376
    table->alias_name_used= my_strcasecmp(table_alias_charset,
 
2377
                                          table_list->schema_table_name,
 
2378
                                          table_list->alias);
 
2379
  table_list->table_name= table->s->table_name.str;
 
2380
  table_list->table_name_length= table->s->table_name.length;
 
2381
  table_list->table= table;
 
2382
  table->next= session->derived_tables;
 
2383
  session->derived_tables= table;
 
2384
  table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
 
2385
 
 
2386
  return false;
 
2387
}
 
2388
 
 
2389
 
 
2390
/*
2081
2391
  Generate select from information_schema table
2082
2392
 
2083
2393
  SYNOPSIS
2111
2421
  return false;
2112
2422
}
2113
2423
 
 
2424
 
 
2425
/*
 
2426
  Fill temporary schema tables before SELECT
 
2427
 
 
2428
  SYNOPSIS
 
2429
    get_schema_tables_result()
 
2430
    join  join which use schema tables
 
2431
    executed_place place where I_S table processed
 
2432
 
 
2433
  RETURN
 
2434
    false success
 
2435
    true  error
 
2436
*/
 
2437
 
 
2438
bool get_schema_tables_result(JOIN *join,
 
2439
                              enum enum_schema_table_state executed_place)
 
2440
{
 
2441
  JoinTable *tmp_join_tab= join->join_tab+join->tables;
 
2442
  Session *session= join->session;
 
2443
  LEX *lex= session->lex;
 
2444
  bool result= 0;
 
2445
 
 
2446
  session->no_warnings_for_error= 1;
 
2447
  for (JoinTable *tab= join->join_tab; tab < tmp_join_tab; tab++)
 
2448
  {
 
2449
    if (!tab->table || !tab->table->pos_in_table_list)
 
2450
      break;
 
2451
 
 
2452
    TableList *table_list= tab->table->pos_in_table_list;
 
2453
    if (table_list->schema_table)
 
2454
    {
 
2455
      bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
 
2456
                          lex->current_select->master_unit()->item);
 
2457
 
 
2458
 
 
2459
      /* skip I_S optimizations specific to get_all_tables */
 
2460
      if (session->lex->describe &&
 
2461
          (table_list->schema_table->isOptimizationPossible() != true))
 
2462
      {
 
2463
        continue;
 
2464
      }
 
2465
 
 
2466
      /*
 
2467
        If schema table is already processed and
 
2468
        the statement is not a subselect then
 
2469
        we don't need to fill this table again.
 
2470
        If schema table is already processed and
 
2471
        schema_table_state != executed_place then
 
2472
        table is already processed and
 
2473
        we should skip second data processing.
 
2474
      */
 
2475
      if (table_list->schema_table_state &&
 
2476
          (!is_subselect || table_list->schema_table_state != executed_place))
 
2477
        continue;
 
2478
 
 
2479
      /*
 
2480
        if table is used in a subselect and
 
2481
        table has been processed earlier with the same
 
2482
        'executed_place' value then we should refresh the table.
 
2483
      */
 
2484
      if (table_list->schema_table_state && is_subselect)
 
2485
      {
 
2486
        table_list->table->cursor->extra(HA_EXTRA_NO_CACHE);
 
2487
        table_list->table->cursor->extra(HA_EXTRA_RESET_STATE);
 
2488
        table_list->table->cursor->ha_delete_all_rows();
 
2489
        table_list->table->free_io_cache();
 
2490
        table_list->table->filesort_free_buffers(true);
 
2491
        table_list->table->null_row= 0;
 
2492
      }
 
2493
      else
 
2494
        table_list->table->cursor->stats.records= 0;
 
2495
 
 
2496
      if (table_list->schema_table->fillTable(session, table_list))
 
2497
      {
 
2498
        result= 1;
 
2499
        join->error= 1;
 
2500
        tab->read_record.cursor= table_list->table->cursor;
 
2501
        table_list->schema_table_state= executed_place;
 
2502
        break;
 
2503
      }
 
2504
      tab->read_record.cursor= table_list->table->cursor;
 
2505
      table_list->schema_table_state= executed_place;
 
2506
    }
 
2507
  }
 
2508
  session->no_warnings_for_error= 0;
 
2509
  return(result);
 
2510
}