~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Monty Taylor
  • Date: 2010-03-11 18:27:20 UTC
  • mfrom: (1333 staging)
  • mto: This revision was merged to the branch mainline in revision 1348.
  • Revision ID: mordred@inaugust.com-20100311182720-hd1h87y6cb1b1mp0
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
#include <drizzled/item/empty_string.h>
42
42
#include "drizzled/plugin/registry.h"
43
43
#include "drizzled/session_list.h"
44
 
#include <drizzled/plugin/info_schema_table.h>
45
44
#include <drizzled/message/schema.pb.h>
46
45
#include <drizzled/plugin/client.h>
47
46
#include <drizzled/cached_directory.h>
72
71
 
73
72
static void store_key_options(String *packet, Table *table, KEY *key_info);
74
73
 
75
 
int wild_case_compare(const CHARSET_INFO * const cs, const char *str,const char *wildstr)
 
74
 
 
75
int wild_case_compare(const CHARSET_INFO * const cs, const char *str, const char *wildstr)
76
76
{
77
77
  register int flag;
 
78
 
78
79
  while (*wildstr)
79
80
  {
80
81
    while (*wildstr && *wildstr != internal::wild_many && *wildstr != internal::wild_one)
115
116
      return (1);
116
117
    }
117
118
  }
 
119
 
118
120
  return (*str != '\0');
119
121
}
120
122
 
121
123
 
122
 
/**
123
 
 * @brief
124
 
 *   Find subdirectories (schemas) in a given directory (datadir).
125
 
 *
126
 
 * @param[in]  session    Thread Cursor
127
 
 * @param[out] files      Put found entries in this list
128
 
 * @param[in]  path       Path to database
129
 
 * @param[in]  wild       Filter for found entries
130
 
 *
131
 
 * @retval false   Success
132
 
 * @retval true    Error
133
 
 */
134
 
static bool find_schemas(Session *session, vector<LEX_STRING*> &files,
135
 
                         const char *path, const char *wild)
136
 
{
137
 
  if (wild && (wild[0] == '\0'))
138
 
    wild= 0;
139
 
 
140
 
  CachedDirectory directory(path);
141
 
 
142
 
  if (directory.fail())
143
 
  {
144
 
    errno= directory.getError();
145
 
    my_error(ER_CANT_READ_DIR, MYF(0), path, errno);
146
 
 
147
 
    return true;
148
 
  }
149
 
 
150
 
  CachedDirectory::Entries entries= directory.getEntries();
151
 
  CachedDirectory::Entries::iterator entry_iter= entries.begin();
152
 
 
153
 
  while (entry_iter != entries.end())
154
 
  {
155
 
    uint32_t file_name_len;
156
 
    char uname[NAME_LEN + 1];                   /* Unencoded name */
157
 
    struct stat entry_stat;
158
 
    CachedDirectory::Entry *entry= *entry_iter;
159
 
 
160
 
    if ((entry->filename == ".") || (entry->filename == ".."))
161
 
    {
162
 
      ++entry_iter;
163
 
      continue;
164
 
    }
165
 
 
166
 
    if (stat(entry->filename.c_str(), &entry_stat))
167
 
    {
168
 
      errno= errno;
169
 
      my_error(ER_CANT_GET_STAT, MYF(0), entry->filename.c_str(), errno);
170
 
      return(true);
171
 
    }
172
 
 
173
 
    if (! S_ISDIR(entry_stat.st_mode))
174
 
    {
175
 
      ++entry_iter;
176
 
      continue;
177
 
    }
178
 
 
179
 
    file_name_len= filename_to_tablename(entry->filename.c_str(), uname,
180
 
                                         sizeof(uname));
181
 
    if (wild && internal::wild_compare(uname, wild, 0))
182
 
    {
183
 
      ++entry_iter;
184
 
      continue;
185
 
    }
186
 
 
187
 
    LEX_STRING *file_name= 0;
188
 
    file_name= session->make_lex_string(file_name, uname, file_name_len, true);
189
 
    if (file_name == NULL)
190
 
      return(true);
191
 
 
192
 
    files.push_back(file_name);
193
 
    ++entry_iter;
194
 
  }
195
 
 
196
 
  return false;
197
 
}
198
 
 
199
 
 
200
124
bool drizzled_show_create(Session *session, TableList *table_list, bool is_if_not_exists)
201
125
{
202
126
  char buff[2048];
267
191
  @returns true if errors are detected, false otherwise.
268
192
*/
269
193
 
270
 
static bool store_db_create_info(const char *dbname, String *buffer, bool if_not_exists)
 
194
static bool store_db_create_info(const char *dbname, string &buffer, bool if_not_exists)
271
195
{
272
196
  message::Schema schema;
273
197
 
274
 
  if (!my_strcasecmp(system_charset_info, dbname,
275
 
                     INFORMATION_SCHEMA_NAME.c_str()))
276
 
  {
277
 
    dbname= INFORMATION_SCHEMA_NAME.c_str();
278
 
  }
279
 
  else
280
 
  {
281
 
    int r= get_database_metadata(dbname, &schema);
282
 
    if(r < 0)
283
 
      return true;
284
 
  }
 
198
  bool found= plugin::StorageEngine::getSchemaDefinition(dbname, schema);
 
199
  if (not found)
 
200
    return false;
285
201
 
286
 
  buffer->length(0);
287
 
  buffer->free();
288
 
  buffer->set_charset(system_charset_info);
289
 
  buffer->append(STRING_WITH_LEN("CREATE DATABASE "));
 
202
  buffer.append("CREATE DATABASE ");
290
203
 
291
204
  if (if_not_exists)
292
 
    buffer->append(STRING_WITH_LEN("IF NOT EXISTS "));
293
 
 
294
 
  buffer->append_identifier(dbname, strlen(dbname));
295
 
 
296
 
  if (schema.has_collation() && strcmp(schema.collation().c_str(),
297
 
                                       default_charset_info->name))
 
205
    buffer.append("IF NOT EXISTS ");
 
206
 
 
207
  buffer.append("`");
 
208
  buffer.append(schema.name());
 
209
  buffer.append("`");
 
210
 
 
211
  if (schema.has_collation())
298
212
  {
299
 
    buffer->append(" COLLATE = ");
300
 
    buffer->append(schema.collation().c_str());
 
213
    buffer.append(" COLLATE = ");
 
214
    buffer.append(schema.collation());
301
215
  }
302
216
 
303
 
  return false;
 
217
  return true;
304
218
}
305
219
 
306
 
bool mysqld_show_create_db(Session *session, char *dbname, bool if_not_exists)
 
220
bool mysqld_show_create_db(Session *session, const char *dbname, bool if_not_exists)
307
221
{
308
 
  char buff[2048];
309
 
  String buffer(buff, sizeof(buff), system_charset_info);
 
222
  string buffer;
310
223
 
311
 
  if (store_db_create_info(dbname, &buffer, if_not_exists))
 
224
  if (not store_db_create_info(dbname, buffer, if_not_exists))
312
225
  {
313
226
    /*
314
227
      This assumes that the only reason for which store_db_create_info()
326
239
    return true;
327
240
 
328
241
  session->client->store(dbname, strlen(dbname));
329
 
  session->client->store(buffer.ptr(), buffer.length());
 
242
  session->client->store(buffer);
330
243
 
331
244
  if (session->client->flush())
332
245
    return true;
 
246
 
333
247
  session->my_eof();
 
248
 
334
249
  return false;
335
250
}
336
251
 
708
623
  uint64_t thread_id;
709
624
  time_t start_time;
710
625
  uint32_t   command;
711
 
  string user, host, db, proc_info, state_info, query;
 
626
  string user;
 
627
  string host;
 
628
  string db;
 
629
  string proc_info;
 
630
  string state_info;
 
631
  string query;
712
632
  thread_info(uint64_t thread_id_arg,
713
633
              time_t start_time_arg,
714
634
              uint32_t command_arg,
724
644
  {}
725
645
};
726
646
 
727
 
void mysqld_list_processes(Session *session,const char *user, bool)
728
 
{
729
 
  Item *field;
730
 
  List<Item> field_list;
731
 
  vector<thread_info> thread_infos;
732
 
 
733
 
  field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
734
 
  field_list.push_back(new Item_empty_string("User",16));
735
 
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
736
 
  field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
737
 
  field->maybe_null= true;
738
 
  field_list.push_back(new Item_empty_string("Command",16));
739
 
  field_list.push_back(new Item_return_int("Time",7, DRIZZLE_TYPE_LONG));
740
 
  field_list.push_back(field=new Item_empty_string("State",30));
741
 
  field->maybe_null= true;
742
 
  field_list.push_back(field=new Item_empty_string("Info", PROCESS_LIST_WIDTH));
743
 
  field->maybe_null= true;
744
 
  if (session->client->sendFields(&field_list))
745
 
    return;
746
 
 
747
 
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
748
 
  if (!session->killed)
749
 
  {
750
 
    Session *tmp;
751
 
    for(vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it)
752
 
    {
753
 
      tmp= *it;
754
 
      Security_context *tmp_sctx= &tmp->security_ctx;
755
 
      internal::st_my_thread_var *mysys_var;
756
 
      if (tmp->client->isConnected() && (!user || (tmp_sctx->user.c_str() && !strcmp(tmp_sctx->user.c_str(), user))))
757
 
      {
758
 
 
759
 
        if ((mysys_var= tmp->mysys_var))
760
 
          pthread_mutex_lock(&mysys_var->mutex);
761
 
 
762
 
        const string tmp_proc_info((tmp->killed == Session::KILL_CONNECTION) ? "Killed" : command_name[tmp->command].str);
763
 
 
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
 
                                           : "");
775
 
        if (mysys_var)
776
 
          pthread_mutex_unlock(&mysys_var->mutex);
777
 
 
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
 
      }
791
 
    }
792
 
  }
793
 
  pthread_mutex_unlock(&LOCK_thread_count);
794
 
  time_t now= time(NULL);
795
 
  for(vector<thread_info>::iterator iter= thread_infos.begin();
796
 
      iter != thread_infos.end();
797
 
      ++iter)
798
 
  {
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
 
 
805
 
    if ((*iter).start_time)
806
 
      session->client->store((uint32_t) (now - (*iter).start_time));
807
 
    else
808
 
      session->client->store();
809
 
 
810
 
    session->client->store((*iter).state_info);
811
 
    session->client->store((*iter).query);
812
 
 
813
 
    if (session->client->flush())
814
 
      break;
815
 
  }
816
 
  session->my_eof();
817
 
 
818
 
  return;
819
 
}
820
 
 
821
647
/*****************************************************************************
822
648
  Status functions
823
649
*****************************************************************************/
824
650
 
825
 
static vector<SHOW_VAR *> all_status_vars;
 
651
static vector<drizzle_show_var *> all_status_vars;
 
652
static vector<drizzle_show_var *> com_status_vars;
826
653
static bool status_vars_inited= 0;
827
654
static int show_var_cmp(const void *var1, const void *var2)
828
655
{
829
 
  return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
 
656
  return strcmp(((drizzle_show_var*)var1)->name, ((drizzle_show_var*)var2)->name);
830
657
}
831
658
 
832
659
class show_var_cmp_functor
833
660
{
834
661
  public:
835
662
  show_var_cmp_functor() { }
836
 
  inline bool operator()(const SHOW_VAR *var1, const SHOW_VAR *var2) const
 
663
  inline bool operator()(const drizzle_show_var *var1, const drizzle_show_var *var2) const
837
664
  {
838
665
    int val= strcmp(var1->name, var2->name);
839
666
    return (val < 0);
844
671
{
845
672
  public:
846
673
  show_var_remove_if() { }
847
 
  inline bool operator()(const SHOW_VAR *curr) const
 
674
  inline bool operator()(const drizzle_show_var *curr) const
848
675
  {
849
676
    return (curr->type == SHOW_UNDEF);
850
677
  }
851
678
};
852
679
 
853
 
SHOW_VAR *getFrontOfStatusVars()
 
680
drizzle_show_var *getFrontOfStatusVars()
854
681
{
855
682
  return all_status_vars.front();
856
683
}
857
684
 
 
685
drizzle_show_var *getCommandStatusVars()
 
686
{
 
687
  return com_status_vars.front();
 
688
}
 
689
 
858
690
/*
859
 
  Adds an array of SHOW_VAR entries to the output of SHOW STATUS
 
691
  Adds an array of drizzle_show_var entries to the output of SHOW STATUS
860
692
 
861
693
  SYNOPSIS
862
 
    add_status_vars(SHOW_VAR *list)
863
 
    list - an array of SHOW_VAR entries to add to all_status_vars
 
694
    add_status_vars(drizzle_show_var *list)
 
695
    list - an array of drizzle_show_var entries to add to all_status_vars
864
696
           the last entry must be {0,0,SHOW_UNDEF}
865
697
 
866
698
  NOTE
872
704
    init_status_vars(), it assumes "startup mode" - neither concurrent access
873
705
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
874
706
*/
875
 
int add_status_vars(SHOW_VAR *list)
 
707
int add_status_vars(drizzle_show_var *list)
876
708
{
877
709
  int res= 0;
878
710
  if (status_vars_inited)
887
719
  return res;
888
720
}
889
721
 
 
722
int add_com_status_vars(drizzle_show_var *list)
 
723
{
 
724
  int res= 0;
 
725
 
 
726
  while (list->name)
 
727
    com_status_vars.insert(com_status_vars.begin(), list++);
 
728
  if (status_vars_inited)
 
729
    sort(com_status_vars.begin(), com_status_vars.end(),
 
730
         show_var_cmp_functor());
 
731
 
 
732
  return res;
 
733
}
 
734
 
890
735
/*
891
736
  Make all_status_vars[] usable for SHOW STATUS
892
737
 
900
745
  status_vars_inited= 1;
901
746
  sort(all_status_vars.begin(), all_status_vars.end(),
902
747
       show_var_cmp_functor());
 
748
  sort(com_status_vars.begin(), com_status_vars.end(),
 
749
       show_var_cmp_functor());
903
750
}
904
751
 
905
752
void reset_status_vars()
906
753
{
907
 
  vector<SHOW_VAR *>::iterator p= all_status_vars.begin();
 
754
  vector<drizzle_show_var *>::iterator p;
 
755
 
 
756
  p= all_status_vars.begin();
908
757
  while (p != all_status_vars.end())
909
758
  {
910
759
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
912
761
      (*p)->value= 0;
913
762
    ++p;
914
763
  }
 
764
 
 
765
  p= com_status_vars.begin();
 
766
  while (p != com_status_vars.end())
 
767
  {
 
768
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
769
    if ((*p)->type == SHOW_LONG)
 
770
      (*p)->value= 0;
 
771
    ++p;
 
772
  }
915
773
}
916
774
 
917
775
/*
926
784
void free_status_vars()
927
785
{
928
786
  all_status_vars.clear();
 
787
  com_status_vars.clear();
929
788
}
930
789
 
931
790
/*
932
 
  Removes an array of SHOW_VAR entries from the output of SHOW STATUS
 
791
  Removes an array of drizzle_show_var entries from the output of SHOW STATUS
933
792
 
934
793
  SYNOPSIS
935
 
    remove_status_vars(SHOW_VAR *list)
936
 
    list - an array of SHOW_VAR entries to remove to all_status_vars
 
794
    remove_status_vars(drizzle_show_var *list)
 
795
    list - an array of drizzle_show_var entries to remove to all_status_vars
937
796
           the last entry must be {0,0,SHOW_UNDEF}
938
797
 
939
798
  NOTE
942
801
    initialization in the mysqld startup.
943
802
*/
944
803
 
945
 
void remove_status_vars(SHOW_VAR *list)
 
804
void remove_status_vars(drizzle_show_var *list)
946
805
{
947
806
  if (status_vars_inited)
948
807
  {
949
808
    pthread_mutex_lock(&LOCK_status);
950
 
    SHOW_VAR *all= all_status_vars.front();
 
809
    drizzle_show_var *all= all_status_vars.front();
951
810
    int a= 0, b= all_status_vars.size(), c= (a+b)/2;
952
811
 
953
812
    for (; list->name; list++)
974
833
  }
975
834
  else
976
835
  {
977
 
    SHOW_VAR *all= all_status_vars.front();
 
836
    drizzle_show_var *all= all_status_vars.front();
978
837
    uint32_t i;
979
838
    for (; list->name; list++)
980
839
    {
995
854
 
996
855
/* collect status for all running threads */
997
856
 
998
 
void calc_sum_of_all_status(STATUS_VAR *to)
 
857
void calc_sum_of_all_status(system_status_var *to)
999
858
{
1000
859
  /* Ensure that thread id not killed during loop */
1001
860
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
1004
863
  *to= global_status_var;
1005
864
 
1006
865
  /* Add to this status from existing threads */
1007
 
  for(vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
866
  for(SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
1008
867
  {
1009
868
    add_to_status(to, &((*it)->status_var));
1010
869
  }
1013
872
  return;
1014
873
}
1015
874
 
1016
 
 
1017
 
static int make_table_list(Session *session, Select_Lex *sel,
1018
 
                           LEX_STRING *db_name, LEX_STRING *table_name)
1019
 
{
1020
 
  Table_ident *table_ident;
1021
 
  table_ident= new Table_ident(*db_name, *table_name);
1022
 
  sel->init_query();
1023
 
  if (! sel->add_table_to_list(session, table_ident, 0, 0, TL_READ))
1024
 
    return 1;
1025
 
  return 0;
1026
 
}
1027
 
 
1028
 
 
1029
 
/**
1030
 
  @brief    Get lookup value from the part of 'WHERE' condition
1031
 
 
1032
 
  @details This function gets lookup value from
1033
 
           the part of 'WHERE' condition if it's possible and
1034
 
           fill appropriate lookup_field_vals struct field
1035
 
           with this value.
1036
 
 
1037
 
  @param[in]      session                   thread Cursor
1038
 
  @param[in]      item_func             part of WHERE condition
1039
 
  @param[in]      table                 I_S table
1040
 
  @param[in, out] lookup_field_vals     Struct which holds lookup values
1041
 
 
1042
 
  @return
1043
 
    0             success
1044
 
    1             error, there can be no matching records for the condition
1045
 
*/
1046
 
 
1047
 
static bool get_lookup_value(Session *session, Item_func *item_func,
1048
 
                             TableList *table,
1049
 
                             LOOKUP_FIELD_VALUES *lookup_field_vals,
1050
 
                             plugin::InfoSchemaTable *schema_table)
1051
 
{
1052
 
  const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
1053
 
    schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
1054
 
  const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
1055
 
    schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
1056
 
 
1057
 
  if (item_func->functype() == Item_func::EQ_FUNC ||
1058
 
      item_func->functype() == Item_func::EQUAL_FUNC)
1059
 
  {
1060
 
    int idx_field, idx_val;
1061
 
    char tmp[MAX_FIELD_WIDTH];
1062
 
    String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
1063
 
    Item_field *item_field;
1064
 
    const CHARSET_INFO * const cs= system_charset_info;
1065
 
 
1066
 
    if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
1067
 
        item_func->arguments()[1]->const_item())
1068
 
    {
1069
 
      idx_field= 0;
1070
 
      idx_val= 1;
1071
 
    }
1072
 
    else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
1073
 
             item_func->arguments()[0]->const_item())
1074
 
    {
1075
 
      idx_field= 1;
1076
 
      idx_val= 0;
1077
 
    }
1078
 
    else
1079
 
      return 0;
1080
 
 
1081
 
    item_field= (Item_field*) item_func->arguments()[idx_field];
1082
 
    if (table->table != item_field->field->table)
1083
 
      return 0;
1084
 
    tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
1085
 
 
1086
 
    /* impossible value */
1087
 
    if (!tmp_str)
1088
 
      return 1;
1089
 
 
1090
 
    /* Lookup value is database name */
1091
 
    if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
1092
 
                               (unsigned char *) item_field->field_name,
1093
 
                               strlen(item_field->field_name), 0))
1094
 
    {
1095
 
      session->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
1096
 
                           tmp_str->length(), false);
1097
 
    }
1098
 
    /* Lookup value is table name */
1099
 
    else if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name2,
1100
 
                                    strlen(field_name2),
1101
 
                                    (unsigned char *) item_field->field_name,
1102
 
                                    strlen(item_field->field_name), 0))
1103
 
    {
1104
 
      session->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
1105
 
                           tmp_str->length(), false);
1106
 
    }
1107
 
  }
1108
 
  return 0;
1109
 
}
1110
 
 
1111
 
 
1112
 
/**
1113
 
  @brief    Calculates lookup values from 'WHERE' condition
1114
 
 
1115
 
  @details This function calculates lookup value(database name, table name)
1116
 
           from 'WHERE' condition if it's possible and
1117
 
           fill lookup_field_vals struct fields with these values.
1118
 
 
1119
 
  @param[in]      session                   thread Cursor
1120
 
  @param[in]      cond                  WHERE condition
1121
 
  @param[in]      table                 I_S table
1122
 
  @param[in, out] lookup_field_vals     Struct which holds lookup values
1123
 
 
1124
 
  @return
1125
 
    0             success
1126
 
    1             error, there can be no matching records for the condition
1127
 
*/
1128
 
 
1129
 
bool calc_lookup_values_from_cond(Session *session, COND *cond, TableList *table,
1130
 
                                  LOOKUP_FIELD_VALUES *lookup_field_vals,
1131
 
                                  plugin::InfoSchemaTable *schema_table)
1132
 
{
1133
 
  if (!cond)
1134
 
    return 0;
1135
 
 
1136
 
  if (cond->type() == Item::COND_ITEM)
1137
 
  {
1138
 
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1139
 
    {
1140
 
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1141
 
      Item *item;
1142
 
      while ((item= li++))
1143
 
      {
1144
 
        if (item->type() == Item::FUNC_ITEM)
1145
 
        {
1146
 
          if (get_lookup_value(session, (Item_func*)item, table, lookup_field_vals, schema_table))
1147
 
            return 1;
1148
 
        }
1149
 
        else
1150
 
        {
1151
 
          if (calc_lookup_values_from_cond(session, item, table, lookup_field_vals, schema_table))
1152
 
            return 1;
1153
 
        }
1154
 
      }
1155
 
    }
1156
 
    return 0;
1157
 
  }
1158
 
  else if (cond->type() == Item::FUNC_ITEM &&
1159
 
           get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals, schema_table))
1160
 
    return 1;
1161
 
  return 0;
1162
 
}
1163
 
 
1164
 
 
1165
 
static bool uses_only_table_name_fields(Item *item, Table *table, plugin::InfoSchemaTable *schema_table)
1166
 
{
1167
 
  if (item->type() == Item::FUNC_ITEM)
1168
 
  {
1169
 
    Item_func *item_func= (Item_func*)item;
1170
 
    for (uint32_t i=0; i<item_func->argument_count(); i++)
1171
 
    {
1172
 
      if (! uses_only_table_name_fields(item_func->arguments()[i], table, schema_table))
1173
 
        return 0;
1174
 
    }
1175
 
  }
1176
 
  else if (item->type() == Item::FIELD_ITEM)
1177
 
  {
1178
 
    Item_field *item_field= (Item_field*)item;
1179
 
    const CHARSET_INFO * const cs= system_charset_info;
1180
 
    const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
1181
 
      schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
1182
 
    const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
1183
 
      schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
1184
 
    if (table != item_field->field->table ||
1185
 
        (cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
1186
 
                               (unsigned char *) item_field->field_name,
1187
 
                               strlen(item_field->field_name), 0) &&
1188
 
         cs->coll->strnncollsp(cs, (unsigned char *) field_name2, strlen(field_name2),
1189
 
                               (unsigned char *) item_field->field_name,
1190
 
                               strlen(item_field->field_name), 0)))
1191
 
      return 0;
1192
 
  }
1193
 
  else if (item->type() == Item::REF_ITEM)
1194
 
    return uses_only_table_name_fields(item->real_item(), table, schema_table);
1195
 
 
1196
 
  if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
1197
 
    return 0;
1198
 
 
1199
 
  return 1;
1200
 
}
1201
 
 
1202
 
 
1203
 
static COND * make_cond_for_info_schema(COND *cond, Table *table, plugin::InfoSchemaTable *schema_table)
1204
 
{
1205
 
  if (!cond)
1206
 
    return (COND*) 0;
1207
 
  if (cond->type() == Item::COND_ITEM)
1208
 
  {
1209
 
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
1210
 
    {
1211
 
      /* Create new top level AND item */
1212
 
      Item_cond_and *new_cond=new Item_cond_and;
1213
 
      if (!new_cond)
1214
 
        return (COND*) 0;
1215
 
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1216
 
      Item *item;
1217
 
      while ((item=li++))
1218
 
      {
1219
 
        Item *fix= make_cond_for_info_schema(item, table, schema_table);
1220
 
        if (fix)
1221
 
          new_cond->argument_list()->push_back(fix);
1222
 
      }
1223
 
      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;
1231
 
      }
1232
 
    }
1233
 
    else
1234
 
    {                                           // Or list
1235
 
      Item_cond_or *new_cond=new Item_cond_or;
1236
 
      if (!new_cond)
1237
 
        return (COND*) 0;
1238
 
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
1239
 
      Item *item;
1240
 
      while ((item=li++))
1241
 
      {
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);
1246
 
      }
1247
 
      new_cond->quick_fix_field();
1248
 
      new_cond->top_level_item();
1249
 
      return new_cond;
1250
 
    }
1251
 
  }
1252
 
 
1253
 
  if (! uses_only_table_name_fields(cond, table, schema_table))
1254
 
    return (COND*) 0;
1255
 
  return cond;
1256
 
}
1257
 
 
1258
 
 
1259
 
/**
1260
 
  @brief   Calculate lookup values(database name, table name)
1261
 
 
1262
 
  @details This function calculates lookup values(database name, table name)
1263
 
           from 'WHERE' condition or wild values (for 'SHOW' commands only)
1264
 
           from LEX struct and fill lookup_field_vals struct field
1265
 
           with these values.
1266
 
 
1267
 
  @param[in]      session                   thread Cursor
1268
 
  @param[in]      cond                  WHERE condition
1269
 
  @param[in]      tables                I_S table
1270
 
  @param[in, out] lookup_field_values   Struct which holds lookup values
1271
 
 
1272
 
  @return
1273
 
    0             success
1274
 
    1             error, there can be no matching records for the condition
1275
 
*/
1276
 
 
1277
 
bool get_lookup_field_values(Session *session, COND *cond, TableList *tables,
1278
 
                             LOOKUP_FIELD_VALUES *lookup_field_values,
1279
 
                             plugin::InfoSchemaTable *schema_table)
1280
 
{
1281
 
  LEX *lex= session->lex;
1282
 
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
1283
 
  memset(lookup_field_values, 0, sizeof(LOOKUP_FIELD_VALUES));
1284
 
  switch (lex->sql_command) {
1285
 
  case SQLCOM_SHOW_DATABASES:
1286
 
    if (wild)
1287
 
    {
1288
 
      lookup_field_values->db_value.str= (char*) wild;
1289
 
      lookup_field_values->db_value.length= strlen(wild);
1290
 
      lookup_field_values->wild_db_value= 1;
1291
 
    }
1292
 
    return 0;
1293
 
  case SQLCOM_SHOW_TABLES:
1294
 
  case SQLCOM_SHOW_TABLE_STATUS:
1295
 
    lookup_field_values->db_value.str= lex->select_lex.db;
1296
 
    lookup_field_values->db_value.length=strlen(lex->select_lex.db);
1297
 
    if (wild)
1298
 
    {
1299
 
      lookup_field_values->table_value.str= (char*)wild;
1300
 
      lookup_field_values->table_value.length= strlen(wild);
1301
 
      lookup_field_values->wild_table_value= 1;
1302
 
    }
1303
 
    return 0;
1304
 
  default:
1305
 
    /*
1306
 
      The "default" is for queries over I_S.
1307
 
      All previous cases handle SHOW commands.
1308
 
    */
1309
 
    return calc_lookup_values_from_cond(session, cond, tables, lookup_field_values, schema_table);
1310
 
  }
1311
 
}
1312
 
 
1313
 
 
1314
 
/**
1315
 
 * Function used for sorting with std::sort within make_db_list.
1316
 
 *
1317
 
 * @returns true if a < b, false otherwise
1318
 
 */
1319
 
 
1320
 
static bool lex_string_sort(const LEX_STRING *a, const LEX_STRING *b)
1321
 
{
1322
 
  return (strcmp(a->str, b->str) < 0);
1323
 
}
1324
 
 
1325
 
 
1326
 
/**
1327
 
 * @brief
1328
 
 *   Create db names list. Information schema name always is first in list
1329
 
 *
1330
 
 * @param[in]  session          Thread Cursor
1331
 
 * @param[out] files            List of db names
1332
 
 * @param[in]  wild             Wild string
1333
 
 * @param[in]  idx_field_vals   idx_field_vals->db_name contains db name or
1334
 
 *                              wild string
1335
 
 * @param[out] with_i_schema    Returns 1 if we added 'IS' name to list
1336
 
 *                              otherwise returns 0
1337
 
 *
1338
 
 * @retval 0   Success
1339
 
 * @retval 1   Error
1340
 
 */
1341
 
int make_db_list(Session *session, vector<LEX_STRING*> &files,
1342
 
                 LOOKUP_FIELD_VALUES *lookup_field_vals,
1343
 
                 bool *with_i_schema)
1344
 
{
1345
 
  LEX_STRING *i_s_name_copy= 0;
1346
 
  i_s_name_copy= session->make_lex_string(i_s_name_copy,
1347
 
                                      INFORMATION_SCHEMA_NAME.c_str(),
1348
 
                                      INFORMATION_SCHEMA_NAME.length(), true);
1349
 
  *with_i_schema= 0;
1350
 
  if (lookup_field_vals->wild_db_value)
1351
 
  {
1352
 
    /*
1353
 
      This part of code is only for SHOW DATABASES command.
1354
 
      idx_field_vals->db_value can be 0 when we don't use
1355
 
      LIKE clause (see also get_index_field_values() function)
1356
 
    */
1357
 
    if (!lookup_field_vals->db_value.str ||
1358
 
        !wild_case_compare(system_charset_info,
1359
 
                           INFORMATION_SCHEMA_NAME.c_str(),
1360
 
                           lookup_field_vals->db_value.str))
1361
 
    {
1362
 
      *with_i_schema= 1;
1363
 
      files.push_back(i_s_name_copy);
1364
 
    }
1365
 
 
1366
 
    if (find_schemas(session, files, drizzle_data_home,
1367
 
                     lookup_field_vals->db_value.str) == true)
1368
 
    {
1369
 
      return 1;
1370
 
    }
1371
 
 
1372
 
    sort(files.begin()+1, files.end(), lex_string_sort);
1373
 
    return 0;
1374
 
  }
1375
 
 
1376
 
 
1377
 
  /*
1378
 
    If we have db lookup vaule we just add it to list and
1379
 
    exit from the function
1380
 
  */
1381
 
  if (lookup_field_vals->db_value.str)
1382
 
  {
1383
 
    if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.c_str(),
1384
 
                       lookup_field_vals->db_value.str))
1385
 
    {
1386
 
      *with_i_schema= 1;
1387
 
      files.push_back(i_s_name_copy);
1388
 
      return 0;
1389
 
    }
1390
 
 
1391
 
    files.push_back(&lookup_field_vals->db_value);
1392
 
    return 0;
1393
 
  }
1394
 
 
1395
 
  /*
1396
 
    Create list of existing databases. It is used in case
1397
 
    of select from information schema table
1398
 
  */
1399
 
  files.push_back(i_s_name_copy);
1400
 
 
1401
 
  *with_i_schema= 1;
1402
 
 
1403
 
  if (find_schemas(session, files, drizzle_data_home, NULL) == true)
1404
 
  {
1405
 
    return 1;
1406
 
  }
1407
 
 
1408
 
  sort(files.begin()+1, files.end(), lex_string_sort);
1409
 
  return 0;
1410
 
}
1411
 
 
1412
 
 
1413
 
/**
1414
 
  @brief          Create table names list
1415
 
 
1416
 
  @details        The function creates the list of table names in
1417
 
                  database
1418
 
 
1419
 
  @param[in]      session                   thread Cursor
1420
 
  @param[in]      table_names           List of table names in database
1421
 
  @param[in]      lex                   pointer to LEX struct
1422
 
  @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
1423
 
  @param[in]      with_i_schema         true means that we add I_S tables to list
1424
 
  @param[in]      db_name               database name
1425
 
 
1426
 
  @return         Operation status
1427
 
    @retval       0           ok
1428
 
    @retval       1           fatal error
1429
 
    @retval       2           Not fatal error; Safe to ignore this cursor list
1430
 
*/
1431
 
 
1432
 
static int
1433
 
make_table_name_list(Session *session, vector<LEX_STRING*> &table_names,
1434
 
                     LOOKUP_FIELD_VALUES *lookup_field_vals,
1435
 
                     bool with_i_schema, LEX_STRING *db_name)
1436
 
{
1437
 
  char path[FN_REFLEN];
1438
 
  set<string> set_of_names;
1439
 
 
1440
 
  build_table_filename(path, sizeof(path), db_name->str, "", false);
1441
 
 
1442
 
  if (!lookup_field_vals->wild_table_value &&
1443
 
      lookup_field_vals->table_value.str)
1444
 
  {
1445
 
    if (with_i_schema)
1446
 
    {
1447
 
      if (plugin::InfoSchemaTable::getTable(lookup_field_vals->table_value.str))
1448
 
      {
1449
 
        table_names.push_back(&lookup_field_vals->table_value);
1450
 
      }
1451
 
    }
1452
 
    else
1453
 
    {
1454
 
      table_names.push_back(&lookup_field_vals->table_value);
1455
 
    }
1456
 
    return 0;
1457
 
  }
1458
 
 
1459
 
  string db(db_name->str);
1460
 
  plugin::StorageEngine::getTableNames(db, set_of_names);
1461
 
 
1462
 
  /*  
1463
 
    New I_S engine will make this go away, so ignore lack of foreach() usage.
1464
 
 
1465
 
    Notice how bad this design is... sure we created a set... but then we
1466
 
    are just pushing to another set. --
1467
 
    Also... callback design won't work, so we need to rewrite this to
1468
 
    feed (which means new I_S). For the moment we will not optimize this.
1469
 
 
1470
 
  */
1471
 
  for (set<string>::iterator it= set_of_names.begin(); it != set_of_names.end(); it++)
1472
 
  {
1473
 
    LEX_STRING *file_name= NULL;
1474
 
    
1475
 
    file_name= session->make_lex_string(file_name, (*it).c_str(),
1476
 
                                        (*it).length(), true);
1477
 
    const char* wild= lookup_field_vals->table_value.str;
1478
 
    if (wild && internal::wild_compare((*it).c_str(), wild, 0))
1479
 
      continue;
1480
 
 
1481
 
    table_names.push_back(file_name);
1482
 
  }
1483
 
 
1484
 
  return 0;
1485
 
}
1486
 
 
1487
 
 
1488
 
/**
1489
 
  @brief          Fill I_S table for SHOW COLUMNS|INDEX commands
1490
 
 
1491
 
  @param[in]      session                      thread Cursor
1492
 
  @param[in]      tables                   TableList for I_S table
1493
 
  @param[in]      schema_table             pointer to I_S structure
1494
 
  @param[in]      open_tables_state_backup pointer to Open_tables_state object
1495
 
                                           which is used to save|restore original
1496
 
                                           status of variables related to
1497
 
                                           open tables state
1498
 
 
1499
 
  @return         Operation status
1500
 
    @retval       0           success
1501
 
    @retval       1           error
1502
 
*/
1503
 
 
1504
 
static int
1505
 
fill_schema_show_cols_or_idxs(Session *session, TableList *tables,
1506
 
                              plugin::InfoSchemaTable *schema_table,
1507
 
                              Open_tables_state *open_tables_state_backup)
1508
 
{
1509
 
  LEX *lex= session->lex;
1510
 
  bool res;
1511
 
  LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
1512
 
  enum_sql_command save_sql_command= lex->sql_command;
1513
 
  TableList *show_table_list= (TableList*) tables->schema_select_lex->
1514
 
    table_list.first;
1515
 
  Table *table= tables->table;
1516
 
  int error= 1;
1517
 
 
1518
 
  lex->all_selects_list= tables->schema_select_lex;
1519
 
  /*
1520
 
    Restore session->temporary_tables to be able to process
1521
 
    temporary tables(only for 'show index' & 'show columns').
1522
 
    This should be changed when processing of temporary tables for
1523
 
    I_S tables will be done.
1524
 
  */
1525
 
  session->temporary_tables= open_tables_state_backup->temporary_tables;
1526
 
  /*
1527
 
    Let us set fake sql_command so views won't try to merge
1528
 
    themselves into main statement. If we don't do this,
1529
 
    SELECT * from information_schema.xxxx will cause problems.
1530
 
    SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
1531
 
  */
1532
 
  lex->sql_command= SQLCOM_SHOW_FIELDS;
1533
 
  res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
1534
 
  lex->sql_command= save_sql_command;
1535
 
  /*
1536
 
    get_all_tables() returns 1 on failure and 0 on success thus
1537
 
    return only these and not the result code of ::process_table()
1538
 
 
1539
 
    We should use show_table_list->alias instead of
1540
 
    show_table_list->table_name because table_name
1541
 
    could be changed during opening of I_S tables. It's safe
1542
 
    to use alias because alias contains original table name
1543
 
    in this case(this part of code is used only for
1544
 
    'show columns' & 'show statistics' commands).
1545
 
  */
1546
 
   table_name= session->make_lex_string(&tmp_lex_string1, show_table_list->alias,
1547
 
                                    strlen(show_table_list->alias), false);
1548
 
   db_name= session->make_lex_string(&tmp_lex_string, show_table_list->db,
1549
 
                                 show_table_list->db_length, false);
1550
 
 
1551
 
 
1552
 
   table->setWriteSet();
1553
 
   error= test(schema_table->processTable(session, show_table_list,
1554
 
                                          table, res, db_name,
1555
 
                                          table_name));
1556
 
   session->temporary_tables= 0;
1557
 
   session->close_tables_for_reopen(&show_table_list);
1558
 
 
1559
 
   return(error);
1560
 
}
1561
 
 
1562
 
 
1563
 
/**
1564
 
  @brief          Fill I_S table for SHOW Table NAMES commands
1565
 
 
1566
 
  @param[in]      session                      thread Cursor
1567
 
  @param[in]      table                    Table struct for I_S table
1568
 
  @param[in]      db_name                  database name
1569
 
  @param[in]      table_name               table name
1570
 
  @param[in]      with_i_schema            I_S table if true
1571
 
 
1572
 
  @return         Operation status
1573
 
    @retval       0           success
1574
 
    @retval       1           error
1575
 
*/
1576
 
 
1577
 
static int fill_schema_table_names(Session *session, Table *table,
1578
 
                                   LEX_STRING *db_name, LEX_STRING *table_name,
1579
 
                                   bool with_i_schema,
1580
 
                                   plugin::InfoSchemaTable *schema_table)
1581
 
{
1582
 
  if (with_i_schema)
1583
 
  {
1584
 
    table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
1585
 
                           system_charset_info);
1586
 
  }
1587
 
  else
1588
 
  {
1589
 
    char path[FN_REFLEN];
1590
 
    (void) build_table_filename(path, sizeof(path), db_name->str,
1591
 
                                table_name->str, false);
1592
 
 
1593
 
      table->field[3]->store(STRING_WITH_LEN("BASE Table"),
1594
 
                             system_charset_info);
1595
 
 
1596
 
    if (session->is_error() && session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
1597
 
    {
1598
 
      session->clear_error();
1599
 
      return 0;
1600
 
    }
1601
 
  }
1602
 
  schema_table->addRow(table->record[0], table->s->reclength);
1603
 
  return 0;
1604
 
}
1605
 
 
1606
 
int plugin::InfoSchemaMethods::fillTable(Session *session,
1607
 
                                         Table *table,
1608
 
                                         plugin::InfoSchemaTable *schema_table)
1609
 
{
1610
 
  LEX *lex= session->lex;
1611
 
  Select_Lex *old_all_select_lex= lex->all_selects_list;
1612
 
  enum_sql_command save_sql_command= lex->sql_command;
1613
 
  Select_Lex *lsel= table->pos_in_table_list->schema_select_lex;
1614
 
  Select_Lex sel;
1615
 
  LOOKUP_FIELD_VALUES lookup_field_vals;
1616
 
  bool with_i_schema;
1617
 
  vector<LEX_STRING*> db_names, table_names;
1618
 
  /* the WHERE clause */
1619
 
  COND *cond= table->reginfo.join_tab->select_cond;
1620
 
  COND *partial_cond= 0;
1621
 
  uint32_t derived_tables= lex->derived_tables;
1622
 
  int error= 1;
1623
 
  Open_tables_state open_tables_state_backup;
1624
 
  Query_tables_list query_tables_list_backup;
1625
 
  bool old_value= session->no_warnings_for_error;
1626
 
 
1627
 
  /*
1628
 
    We should not introduce deadlocks even if we already have some
1629
 
    tables open and locked, since we won't lock tables which we will
1630
 
    open and will ignore possible name-locks for these tables.
1631
 
  */
1632
 
  session->reset_n_backup_open_tables_state(&open_tables_state_backup);
1633
 
 
1634
 
  /*
1635
 
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
1636
 
    see sql_parse.cc, prepare_schema_table() function where
1637
 
    this values are initialized
1638
 
  */
1639
 
  if (lsel && lsel->table_list.first)
1640
 
  {
1641
 
    error= fill_schema_show_cols_or_idxs(session, table->pos_in_table_list, schema_table,
1642
 
                                         &open_tables_state_backup);
1643
 
    goto err;
1644
 
  }
1645
 
 
1646
 
  if (get_lookup_field_values(session, 
1647
 
                              cond, 
1648
 
                              table->pos_in_table_list, 
1649
 
                              &lookup_field_vals,
1650
 
                              schema_table))
1651
 
  {
1652
 
    error= 0;
1653
 
    goto err;
1654
 
  }
1655
 
 
1656
 
  if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
1657
 
  {
1658
 
    /*
1659
 
      if lookup value is empty string then
1660
 
      it's impossible table name or db name
1661
 
    */
1662
 
    if ((lookup_field_vals.db_value.str && !lookup_field_vals.db_value.str[0]) ||
1663
 
        (lookup_field_vals.table_value.str && !lookup_field_vals.table_value.str[0]))
1664
 
    {
1665
 
      error= 0;
1666
 
      goto err;
1667
 
    }
1668
 
  }
1669
 
 
1670
 
  if (lookup_field_vals.db_value.length &&
1671
 
      !lookup_field_vals.wild_db_value)
1672
 
    table->pos_in_table_list->has_db_lookup_value= true;
1673
 
 
1674
 
  if (lookup_field_vals.table_value.length &&
1675
 
      !lookup_field_vals.wild_table_value)
1676
 
    table->pos_in_table_list->has_table_lookup_value= true;
1677
 
 
1678
 
  if (table->pos_in_table_list->has_db_lookup_value && 
1679
 
      table->pos_in_table_list->has_table_lookup_value)
1680
 
    partial_cond= 0;
1681
 
  else
1682
 
    partial_cond= make_cond_for_info_schema(cond, table, schema_table);
1683
 
 
1684
 
  if (lex->describe)
1685
 
  {
1686
 
    /* EXPLAIN SELECT */
1687
 
    error= 0;
1688
 
    goto err;
1689
 
  }
1690
 
 
1691
 
  table->setWriteSet();
1692
 
  if (make_db_list(session, db_names, &lookup_field_vals, &with_i_schema))
1693
 
    goto err;
1694
 
 
1695
 
  for (vector<LEX_STRING*>::iterator db_name= db_names.begin(); db_name != db_names.end(); ++db_name )
1696
 
  {
1697
 
    session->no_warnings_for_error= 1;
1698
 
    table_names.clear();
1699
 
    int res= make_table_name_list(session, table_names,
1700
 
                                  &lookup_field_vals,
1701
 
                                  with_i_schema, *db_name);
1702
 
 
1703
 
    if (res == 2)   /* Not fatal error, continue */
1704
 
      continue;
1705
 
 
1706
 
    if (res)
1707
 
      goto err;
1708
 
 
1709
 
    
1710
 
    for (vector<LEX_STRING*>::iterator table_name= table_names.begin(); table_name != table_names.end(); ++table_name)
1711
 
    {
1712
 
      table->restoreRecordAsDefault();
1713
 
      table->field[schema_table->getFirstColumnIndex()]->
1714
 
        store((*db_name)->str, (*db_name)->length, system_charset_info);
1715
 
      table->field[schema_table->getSecondColumnIndex()]->
1716
 
        store((*table_name)->str, (*table_name)->length, system_charset_info);
1717
 
 
1718
 
      if (!partial_cond || partial_cond->val_int())
1719
 
      {
1720
 
        /* SHOW Table NAMES command */
1721
 
        if (schema_table->getTableName().compare("TABLE_NAMES") == 0)
1722
 
        {
1723
 
          if (fill_schema_table_names(session, 
1724
 
                                      table, 
1725
 
                                      *db_name,
1726
 
                                      *table_name, 
1727
 
                                      with_i_schema,
1728
 
                                      schema_table))
1729
 
            continue;
1730
 
        }
1731
 
        else
1732
 
        {
1733
 
          LEX_STRING tmp_lex_string, orig_db_name;
1734
 
          /*
1735
 
            Set the parent lex of 'sel' because it is needed by
1736
 
            sel.init_query() which is called inside make_table_list.
1737
 
          */
1738
 
          session->no_warnings_for_error= 1;
1739
 
          sel.parent_lex= lex;
1740
 
          /* 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
 
          {
1746
 
            goto err;
1747
 
          }
1748
 
 
1749
 
          if (make_table_list(session, &sel, *db_name, *table_name))
1750
 
            goto err;
1751
 
 
1752
 
          TableList *show_table_list= (TableList*) sel.table_list.first;
1753
 
          lex->all_selects_list= &sel;
1754
 
          lex->derived_tables= 0;
1755
 
          lex->sql_command= SQLCOM_SHOW_FIELDS;
1756
 
          show_table_list->i_s_requested_object=
1757
 
            schema_table->getRequestedObject();
1758
 
          res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
1759
 
          lex->sql_command= save_sql_command;
1760
 
          /*
1761
 
            XXX->  show_table_list has a flag i_is_requested,
1762
 
            and when it's set, openTables()
1763
 
            can return an error without setting an error message
1764
 
            in Session, which is a hack. This is why we have to
1765
 
            check for res, then for session->is_error() only then
1766
 
            for session->main_da.sql_errno().
1767
 
          */
1768
 
          if (res && session->is_error() &&
1769
 
              session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
1770
 
          {
1771
 
            /*
1772
 
              Hide error for not existing table.
1773
 
              This error can occur for example when we use
1774
 
              where condition with db name and table name and this
1775
 
              table does not exist.
1776
 
            */
1777
 
            res= 0;
1778
 
            session->clear_error();
1779
 
          }
1780
 
          else
1781
 
          {
1782
 
            /*
1783
 
              We should use show_table_list->alias instead of
1784
 
              show_table_list->table_name because table_name
1785
 
              could be changed during opening of I_S tables. It's safe
1786
 
              to use alias because alias contains original table name
1787
 
              in this case.
1788
 
            */
1789
 
            session->make_lex_string(&tmp_lex_string, show_table_list->alias,
1790
 
                                     strlen(show_table_list->alias), false);
1791
 
            res= schema_table->processTable(session, show_table_list, table,
1792
 
                                            res, &orig_db_name,
1793
 
                                            &tmp_lex_string);
1794
 
            session->close_tables_for_reopen(&show_table_list);
1795
 
          }
1796
 
          assert(!lex->query_tables_own_last);
1797
 
          if (res)
1798
 
            goto err;
1799
 
        }
1800
 
      }
1801
 
    }
1802
 
    /*
1803
 
      If we have information schema its always the first table and only
1804
 
      the first table. Reset for other tables.
1805
 
    */
1806
 
    with_i_schema= 0;
1807
 
  }
1808
 
 
1809
 
  error= 0;
1810
 
 
1811
 
err:
1812
 
  session->restore_backup_open_tables_state(&open_tables_state_backup);
1813
 
  lex->derived_tables= derived_tables;
1814
 
  lex->all_selects_list= old_all_select_lex;
1815
 
  lex->sql_command= save_sql_command;
1816
 
  session->no_warnings_for_error= old_value;
1817
 
  return(error);
1818
 
}
1819
 
 
1820
 
 
1821
 
/**
1822
 
  @brief    Store field characteristics into appropriate I_S table columns
1823
 
 
1824
 
  @param[in]      table             I_S table
1825
 
  @param[in]      field             processed field
1826
 
  @param[in]      cs                I_S table charset
1827
 
  @param[in]      offset            offset from beginning of table
1828
 
                                    to DATE_TYPE column in I_S table
1829
 
 
1830
 
  @return         void
1831
 
*/
1832
 
 
1833
 
static void store_column_type(Table *table, Field *field,
1834
 
                              const CHARSET_INFO * const cs,
1835
 
                              uint32_t offset)
1836
 
{
1837
 
  bool is_blob;
1838
 
  int decimals, field_length;
1839
 
  const char *tmp_buff;
1840
 
  char column_type_buff[MAX_FIELD_WIDTH];
1841
 
  String column_type(column_type_buff, sizeof(column_type_buff), cs);
1842
 
 
1843
 
  field->sql_type(column_type);
1844
 
  /* DTD_IDENTIFIER column */
1845
 
  table->field[offset + 7]->store(column_type.ptr(), column_type.length(), cs);
1846
 
  table->field[offset + 7]->set_notnull();
1847
 
  tmp_buff= strchr(column_type.ptr(), '(');
1848
 
  /* DATA_TYPE column */
1849
 
  table->field[offset]->store(column_type.ptr(),
1850
 
                         (tmp_buff ? tmp_buff - column_type.ptr() :
1851
 
                          column_type.length()), cs);
1852
 
  is_blob= (field->type() == DRIZZLE_TYPE_BLOB);
1853
 
  if (field->has_charset() || is_blob ||
1854
 
      field->real_type() == DRIZZLE_TYPE_VARCHAR)  // For varbinary type
1855
 
  {
1856
 
    uint32_t octet_max_length= field->max_display_length();
1857
 
    if (is_blob && octet_max_length != (uint32_t) 4294967295U)
1858
 
      octet_max_length /= field->charset()->mbmaxlen;
1859
 
    int64_t char_max_len= is_blob ?
1860
 
      (int64_t) octet_max_length / field->charset()->mbminlen :
1861
 
      (int64_t) octet_max_length / field->charset()->mbmaxlen;
1862
 
    /* CHARACTER_MAXIMUM_LENGTH column*/
1863
 
    table->field[offset + 1]->store(char_max_len, true);
1864
 
    table->field[offset + 1]->set_notnull();
1865
 
    /* CHARACTER_OCTET_LENGTH column */
1866
 
    table->field[offset + 2]->store((int64_t) octet_max_length, true);
1867
 
    table->field[offset + 2]->set_notnull();
1868
 
  }
1869
 
 
1870
 
  /*
1871
 
    Calculate field_length and decimals.
1872
 
    They are set to -1 if they should not be set (we should return NULL)
1873
 
  */
1874
 
 
1875
 
  decimals= field->decimals();
1876
 
  switch (field->type()) {
1877
 
  case DRIZZLE_TYPE_DECIMAL:
1878
 
    field_length= ((Field_decimal*) field)->precision;
1879
 
    break;
1880
 
  case DRIZZLE_TYPE_LONG:
1881
 
  case DRIZZLE_TYPE_LONGLONG:
1882
 
    field_length= field->max_display_length() - 1;
1883
 
    break;
1884
 
  case DRIZZLE_TYPE_DOUBLE:
1885
 
    field_length= field->field_length;
1886
 
    if (decimals == NOT_FIXED_DEC)
1887
 
      decimals= -1;                           // return NULL
1888
 
    break;
1889
 
  default:
1890
 
    field_length= decimals= -1;
1891
 
    break;
1892
 
  }
1893
 
 
1894
 
  /* NUMERIC_PRECISION column */
1895
 
  if (field_length >= 0)
1896
 
  {
1897
 
    table->field[offset + 3]->store((int64_t) field_length, true);
1898
 
    table->field[offset + 3]->set_notnull();
1899
 
  }
1900
 
  /* NUMERIC_SCALE column */
1901
 
  if (decimals >= 0)
1902
 
  {
1903
 
    table->field[offset + 4]->store((int64_t) decimals, true);
1904
 
    table->field[offset + 4]->set_notnull();
1905
 
  }
1906
 
  if (field->has_charset())
1907
 
  {
1908
 
    /* CHARACTER_SET_NAME column*/
1909
 
    tmp_buff= field->charset()->csname;
1910
 
    table->field[offset + 5]->store(tmp_buff, strlen(tmp_buff), cs);
1911
 
    table->field[offset + 5]->set_notnull();
1912
 
    /* COLLATION_NAME column */
1913
 
    tmp_buff= field->charset()->name;
1914
 
    table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs);
1915
 
    table->field[offset + 6]->set_notnull();
1916
 
  }
1917
 
}
1918
 
 
1919
 
 
1920
 
int plugin::InfoSchemaMethods::processTable(
1921
 
            plugin::InfoSchemaTable *store_table,
1922
 
            Session *session, 
1923
 
            TableList *tables,
1924
 
                                    Table *table, bool res,
1925
 
                                    LEX_STRING *db_name,
1926
 
                                    LEX_STRING *table_name)
1927
 
{
1928
 
  LEX *lex= session->lex;
1929
 
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
1930
 
  const CHARSET_INFO * const cs= system_charset_info;
1931
 
  Table *show_table;
1932
 
  TableShare *show_table_share;
1933
 
  Field **ptr, *field, *timestamp_field;
1934
 
  int count;
1935
 
 
1936
 
  if (res)
1937
 
  {
1938
 
    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
1939
 
    {
1940
 
      /*
1941
 
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
1942
 
        rather than in SHOW COLUMNS
1943
 
      */
1944
 
      if (session->is_error())
1945
 
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1946
 
                     session->main_da.sql_errno(), session->main_da.message());
1947
 
      session->clear_error();
1948
 
      res= 0;
1949
 
    }
1950
 
    return(res);
1951
 
  }
1952
 
 
1953
 
  show_table= tables->table;
1954
 
  show_table_share= show_table->s;
1955
 
  count= 0;
1956
 
 
1957
 
  ptr= show_table_share->field;
1958
 
  timestamp_field= show_table_share->timestamp_field;
1959
 
 
1960
 
  /* For the moment we just set everything to read */
1961
 
  if (!show_table->read_set)
1962
 
  {
1963
 
    show_table->def_read_set.setAll();
1964
 
    show_table->read_set= &show_table->def_read_set;
1965
 
  }
1966
 
  show_table->use_all_columns();               // Required for default
1967
 
 
1968
 
  for (; (field= *ptr) ; ptr++)
1969
 
  {
1970
 
    unsigned char *pos;
1971
 
    char tmp[MAX_FIELD_WIDTH];
1972
 
    String type(tmp,sizeof(tmp), system_charset_info);
1973
 
    char *end;
1974
 
 
1975
 
    /* to satisfy 'field->val_str' ASSERTs */
1976
 
    field->table= show_table;
1977
 
    show_table->in_use= session;
1978
 
 
1979
 
    if (wild && wild[0] &&
1980
 
        wild_case_compare(system_charset_info, field->field_name,wild))
1981
 
      continue;
1982
 
 
1983
 
    count++;
1984
 
    /* Get default row, with all NULL fields set to NULL */
1985
 
    table->restoreRecordAsDefault();
1986
 
 
1987
 
    table->field[1]->store(db_name->str, db_name->length, cs);
1988
 
    table->field[2]->store(table_name->str, table_name->length, cs);
1989
 
    table->field[3]->store(field->field_name, strlen(field->field_name),
1990
 
                           cs);
1991
 
    table->field[4]->store((int64_t) count, true);
1992
 
 
1993
 
    if (get_field_default_value(timestamp_field, field, &type, 0))
1994
 
    {
1995
 
      table->field[5]->store(type.ptr(), type.length(), cs);
1996
 
      table->field[5]->set_notnull();
1997
 
    }
1998
 
    pos=(unsigned char*) ((field->flags & NOT_NULL_FLAG) ?  "NO" : "YES");
1999
 
    table->field[6]->store((const char*) pos,
2000
 
                           strlen((const char*) pos), cs);
2001
 
    store_column_type(table, field, cs, 7);
2002
 
 
2003
 
    pos=(unsigned char*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
2004
 
                 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
2005
 
                 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
2006
 
    table->field[15]->store((const char*) pos,
2007
 
                            strlen((const char*) pos), cs);
2008
 
 
2009
 
    end= tmp;
2010
 
    if (field->unireg_check == Field::NEXT_NUMBER)
2011
 
      table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
2012
 
    if (timestamp_field == field &&
2013
 
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
2014
 
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
2015
 
                              cs);
2016
 
    table->field[18]->store(field->comment.str, field->comment.length, cs);
2017
 
    {
2018
 
      enum column_format_type column_format= (enum column_format_type)
2019
 
        ((field->flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
2020
 
      pos=(unsigned char*)"Default";
2021
 
      table->field[19]->store((const char*) pos,
2022
 
                              strlen((const char*) pos), cs);
2023
 
      pos=(unsigned char*)(column_format == COLUMN_FORMAT_TYPE_DEFAULT ? "Default" :
2024
 
                   column_format == COLUMN_FORMAT_TYPE_FIXED ? "Fixed" :
2025
 
                                                             "Dynamic");
2026
 
      table->field[20]->store((const char*) pos,
2027
 
                              strlen((const char*) pos), cs);
2028
 
    }
2029
 
    store_table->addRow(table->record[0], table->s->reclength);
2030
 
  }
2031
 
  return(0);
2032
 
}
2033
 
 
2034
 
 
2035
 
/*
2036
 
  For old SHOW compatibility. It is used when
2037
 
  old SHOW doesn't have generated column names
2038
 
  Make list of fields for SHOW
2039
 
 
2040
 
  SYNOPSIS
2041
 
    plugin::InfoSchemaMethods::oldFormat()
2042
 
    session                     thread Cursor
2043
 
    schema_table        pointer to 'schema_tables' element
2044
 
 
2045
 
  RETURN
2046
 
   1    error
2047
 
   0    success
2048
 
*/
2049
 
 
2050
 
int plugin::InfoSchemaMethods::oldFormat(Session *session, plugin::InfoSchemaTable *schema_table)
2051
 
  const
2052
 
{
2053
 
  Name_resolution_context *context= &session->lex->select_lex.context;
2054
 
  const plugin::InfoSchemaTable::Columns columns= schema_table->getColumns();
2055
 
  plugin::InfoSchemaTable::Columns::const_iterator iter= columns.begin();
2056
 
 
2057
 
  while (iter != columns.end())
2058
 
  {
2059
 
    const plugin::ColumnInfo *column= *iter;
2060
 
    if (column->getOldName().length() != 0)
2061
 
    {
2062
 
      Item_field *field= new Item_field(context,
2063
 
                                        NULL, NULL,
2064
 
                                        column->getName().c_str());
2065
 
      if (field)
2066
 
      {
2067
 
        field->set_name(column->getOldName().c_str(),
2068
 
                        column->getOldName().length(),
2069
 
                        system_charset_info);
2070
 
        if (session->add_item_to_list(field))
2071
 
          return 1;
2072
 
      }
2073
 
    }
2074
 
    ++iter;
2075
 
  }
2076
 
  return 0;
2077
 
}
2078
 
 
2079
 
 
2080
 
/*
2081
 
  Generate select from information_schema table
2082
 
 
2083
 
  SYNOPSIS
2084
 
    make_schema_select()
2085
 
    session                  thread Cursor
2086
 
    sel                  pointer to Select_Lex
2087
 
    schema_table_name    name of 'schema_tables' element
2088
 
 
2089
 
  RETURN
2090
 
    true on error
2091
 
*/
2092
 
 
2093
 
bool make_schema_select(Session *session, Select_Lex *sel,
2094
 
                        const string& schema_table_name)
2095
 
{
2096
 
  plugin::InfoSchemaTable *schema_table= plugin::InfoSchemaTable::getTable(schema_table_name.c_str());
2097
 
  LEX_STRING db, table;
2098
 
  /*
2099
 
     We have to make non const db_name & table_name
2100
 
     because of lower_case_table_names
2101
 
  */
2102
 
  session->make_lex_string(&db, INFORMATION_SCHEMA_NAME.c_str(),
2103
 
                       INFORMATION_SCHEMA_NAME.length(), 0);
2104
 
  session->make_lex_string(&table, schema_table->getTableName().c_str(),
2105
 
                           schema_table->getTableName().length(), 0);
2106
 
  if (schema_table->oldFormat(session, schema_table) ||   /* Handle old syntax */
2107
 
      ! sel->add_table_to_list(session, new Table_ident(db, table), 0, 0, TL_READ))
2108
 
  {
2109
 
    return true;
2110
 
  }
2111
 
  return false;
2112
 
}
2113
 
 
2114
875
} /* namespace drizzled */