~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzle.cc

  • Committer: Brian Aker
  • Date: 2009-03-12 22:13:42 UTC
  • mfrom: (923.2.9 mordred)
  • Revision ID: brian@tangent.org-20090312221342-s0v2g1jeq4jub0p5
Merge of Monty's work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
125
125
#define vidattr(A) {}      // Can't get this to work
126
126
#endif
127
127
 
128
 
#include "completion_hash.h"
 
128
#include <iostream>
 
129
#include <functional>
 
130
#include <map>
129
131
 
130
132
using namespace std;
131
133
 
149
151
} STATUS;
150
152
 
151
153
 
152
 
static HashTable ht;
 
154
static map<string, string>::iterator completion_iter;
 
155
static map<string, string>::iterator completion_end;
 
156
static map<string, string> completion_map;
 
157
static string completion_string;
 
158
 
153
159
static char **defaults_argv;
154
160
 
155
161
enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
197
203
static char default_pager[FN_REFLEN];
198
204
static char pager[FN_REFLEN], outfile[FN_REFLEN];
199
205
static FILE *PAGER, *OUTFILE;
200
 
static MEM_ROOT hash_mem_root;
201
206
static uint32_t prompt_counter;
202
207
static char delimiter[16]= DEFAULT_DELIMITER;
203
208
static uint32_t delimiter_length= 1;
1095
1100
    my_end(0);
1096
1101
    exit(1);
1097
1102
  }
1098
 
  completion_hash_init(&ht, 128);
1099
 
  init_alloc_root(&hash_mem_root, 16384, 0);
1100
1103
  memset(&drizzle, 0, sizeof(drizzle));
1101
1104
  if (sql_connect(current_host,current_db,current_user,opt_password,
1102
1105
                  opt_silent))
1193
1196
      my_rename(histfile_tmp, histfile, MYF(MY_WME));
1194
1197
  }
1195
1198
  batch_readline_end(status.line_buff);
1196
 
  completion_hash_free(&ht);
1197
 
  free_root(&hash_mem_root,MYF(0));
1198
1199
 
1199
1200
  if (sig >= 0)
1200
1201
    put_info(sig ? _("Aborted") : _("Bye"), INFO_RESULT,0,0);
2221
2222
    return (char**) 0;
2222
2223
}
2223
2224
 
 
2225
inline string lower_string(const string &from_string)
 
2226
{
 
2227
  string to_string= from_string;
 
2228
  transform(to_string.begin(), to_string.end(),
 
2229
            to_string.begin(), ::tolower);
 
2230
  return to_string;
 
2231
}
 
2232
inline string lower_string(const char * from_string)
 
2233
{
 
2234
  string to_string= from_string;
 
2235
  return lower_string(to_string);
 
2236
}
 
2237
 
 
2238
template <class T>
 
2239
class CompletionMatch :
 
2240
  public unary_function<const string&, bool>
 
2241
{
 
2242
  string match_text; 
 
2243
  T match_func;
 
2244
public:
 
2245
  CompletionMatch(string text) : match_text(text) {}
 
2246
  inline bool operator() (const pair<string,string> &match_against) const
 
2247
  {
 
2248
    string sub_match=
 
2249
      lower_string(match_against.first.substr(0,match_text.size()));
 
2250
    return match_func(sub_match,match_text);
 
2251
  }
 
2252
};
 
2253
 
 
2254
 
 
2255
 
2224
2256
extern "C"
2225
 
char *new_command_generator(const char *text,int state)
 
2257
char *new_command_generator(const char *text, int state)
2226
2258
{
2227
 
  static int textlen;
2228
 
  char *ptr;
2229
 
  static Bucket *b;
2230
 
  static entry *e;
2231
 
  static uint32_t i;
2232
2259
 
2233
2260
  if (!state)
2234
 
    textlen=(uint32_t) strlen(text);
2235
 
 
2236
 
  if (textlen>0)
2237
 
  {            /* lookup in the hash */
2238
 
    if (!state)
2239
 
    {
2240
 
      uint32_t len;
2241
 
 
2242
 
      b = find_all_matches(&ht,text,(uint32_t) strlen(text),&len);
2243
 
      if (!b)
2244
 
        return NULL;
2245
 
      e = b->pData;
2246
 
    }
2247
 
 
2248
 
    if (e)
2249
 
    {
2250
 
      ptr= strdup(e->str);
2251
 
      e = e->pNext;
2252
 
      return ptr;
2253
 
    }
2254
 
  }
2255
 
  else
2256
 
  { /* traverse the entire hash, ugly but works */
2257
 
 
2258
 
    if (!state)
2259
 
    {
2260
 
      /* find the first used bucket */
2261
 
      for (i=0 ; i < ht.nTableSize ; i++)
2262
 
      {
2263
 
        if (ht.arBuckets[i])
2264
 
        {
2265
 
          b = ht.arBuckets[i];
2266
 
          e = b->pData;
2267
 
          break;
2268
 
        }
2269
 
      }
2270
 
    }
2271
 
    ptr= NULL;
2272
 
    while (e && !ptr)
2273
 
    {          /* find valid entry in bucket */
2274
 
      if ((uint32_t) strlen(e->str) == b->nKeyLength)
2275
 
        ptr = strdup(e->str);
2276
 
      /* find the next used entry */
2277
 
      e = e->pNext;
2278
 
      if (!e)
2279
 
      { /* find the next used bucket */
2280
 
        b = b->pNext;
2281
 
        if (!b)
2282
 
        {
2283
 
          for (i++ ; i<ht.nTableSize; i++)
2284
 
          {
2285
 
            if (ht.arBuckets[i])
2286
 
            {
2287
 
              b = ht.arBuckets[i];
2288
 
              e = b->pData;
2289
 
              break;
2290
 
            }
2291
 
          }
2292
 
        }
2293
 
        else
2294
 
          e = b->pData;
2295
 
      }
2296
 
    }
2297
 
    if (ptr)
2298
 
      return ptr;
2299
 
  }
2300
 
  return NULL;
 
2261
  {
 
2262
    completion_string= lower_string(text);
 
2263
    if (completion_string.size() == 0)
 
2264
    {
 
2265
      completion_iter= completion_map.begin();
 
2266
      completion_end= completion_map.end();
 
2267
    }
 
2268
    else
 
2269
    {
 
2270
      completion_iter= find_if(completion_map.begin(), completion_map.end(),
 
2271
                               CompletionMatch<equal_to<string> >(completion_string));
 
2272
      completion_end= find_if(completion_iter, completion_map.end(),
 
2273
                              CompletionMatch<not_equal_to<string> >(completion_string));
 
2274
    }
 
2275
  }
 
2276
  if (completion_iter == completion_end || (size_t)state > completion_map.size())
 
2277
    return NULL;
 
2278
  char *result= (char *)malloc((*completion_iter).second.size()+1);
 
2279
  strcpy(result, (*completion_iter).second.c_str());
 
2280
  completion_iter++;
 
2281
  return result;
2301
2282
}
2302
2283
 
2303
 
 
2304
2284
/* Build up the completion hash */
2305
2285
 
2306
2286
static void build_completion_hash(bool rehash, bool write_info)
2308
2288
  COMMANDS *cmd=commands;
2309
2289
  DRIZZLE_RES *databases=0,*tables=0;
2310
2290
  DRIZZLE_RES *fields;
2311
 
  static char ***field_names= 0;
2312
2291
  DRIZZLE_ROW database_row,table_row;
2313
2292
  DRIZZLE_FIELD *sql_field;
2314
 
  char buf[NAME_LEN*2+2];     // table name plus field name plus 2
2315
 
  int i,j,num_fields;
 
2293
  string tmp_str, tmp_str_lower;
2316
2294
 
2317
2295
 
2318
2296
  if (status.batch || quick || !current_db)
2320
2298
  if (!rehash)
2321
2299
    return;
2322
2300
 
2323
 
  /* Free old used memory */
2324
 
  if (field_names)
2325
 
    field_names=0;
2326
 
  completion_hash_clean(&ht);
2327
 
  free_root(&hash_mem_root,MYF(0));
 
2301
  completion_map.clear();
2328
2302
 
2329
2303
  /* hash this file's known subset of SQL commands */
2330
2304
  while (cmd->name) {
2331
 
    add_word(&ht,(char*) cmd->name);
 
2305
    tmp_str= cmd->name;
 
2306
    tmp_str_lower= lower_string(tmp_str);
 
2307
    completion_map[tmp_str_lower]= tmp_str;
2332
2308
    cmd++;
2333
2309
  }
2334
2310
 
2343
2319
    {
2344
2320
      while ((database_row=drizzleclient_fetch_row(databases)))
2345
2321
      {
2346
 
        char *str=strdup_root(&hash_mem_root, (char*) database_row[0]);
2347
 
        if (str)
2348
 
          add_word(&ht,(char*) str);
 
2322
        tmp_str= database_row[0];
 
2323
        tmp_str_lower= lower_string(tmp_str);
 
2324
        completion_map[tmp_str_lower]= tmp_str;
2349
2325
      }
2350
2326
      drizzleclient_free_result(databases);
2351
2327
    }
2365
2341
      }
2366
2342
      while ((table_row=drizzleclient_fetch_row(tables)))
2367
2343
      {
2368
 
        char *str=strdup_root(&hash_mem_root, (char*) table_row[0]);
2369
 
        if (str &&
2370
 
            !completion_hash_exists(&ht,(char*) str, (uint32_t) strlen(str)))
2371
 
          add_word(&ht,str);
 
2344
        tmp_str= table_row[0];
 
2345
        tmp_str_lower= lower_string(tmp_str);
 
2346
        completion_map[tmp_str_lower]= tmp_str;
2372
2347
      }
2373
2348
    }
2374
2349
  }
2379
2354
    return;
2380
2355
  }
2381
2356
  drizzleclient_data_seek(tables,0);
2382
 
  if (!(field_names= (char ***) alloc_root(&hash_mem_root,sizeof(char **) *
2383
 
                                           (uint32_t) (drizzleclient_num_rows(tables)+1))))
2384
 
  {
2385
 
    drizzleclient_free_result(tables);
2386
 
    return;
2387
 
  }
2388
 
  i=0;
 
2357
 
2389
2358
  while ((table_row=drizzleclient_fetch_row(tables)))
2390
2359
  {
2391
2360
    string query;
2392
2361
 
2393
 
    query.append("show fields in '");
 
2362
    query.append("show fields in `");
2394
2363
    query.append(table_row[0]);
2395
 
    query.append("'");
 
2364
    query.append("`");
2396
2365
    
2397
 
    if ((drizzleclient_real_query(&drizzle, query.c_str(), query.length()) == 0))
 
2366
    if (drizzleclient_query(&drizzle, query.c_str()) == 0)
2398
2367
    {
2399
2368
      fields= drizzleclient_store_result(&drizzle);
2400
2369
      if (fields) 
2401
2370
      {
2402
 
        num_fields=drizzleclient_num_fields(fields);
2403
 
        if (!(field_names[i] = (char **) alloc_root(&hash_mem_root,
2404
 
                                                    sizeof(char *) *
2405
 
                                                    (num_fields*2+1))))
2406
 
        {
2407
 
          drizzleclient_free_result(fields);
2408
 
          break;
2409
 
        }
2410
 
        field_names[i][num_fields*2]= '\0';
2411
 
        j= 0;
2412
2371
        while ((sql_field=drizzleclient_fetch_field(fields)))
2413
2372
        {
2414
 
          sprintf(buf,"%.64s.%.64s",table_row[0],sql_field->name);
2415
 
          field_names[i][j] = strdup_root(&hash_mem_root,buf);
2416
 
          add_word(&ht,field_names[i][j]);
2417
 
          field_names[i][num_fields+j] = strdup_root(&hash_mem_root,
2418
 
                                                     sql_field->name);
2419
 
          if (!completion_hash_exists(&ht,field_names[i][num_fields+j],
2420
 
                                      (uint32_t) strlen(field_names[i][num_fields+j])))
2421
 
            add_word(&ht,field_names[i][num_fields+j]);
2422
 
          j++;
 
2373
          tmp_str=table_row[0];
 
2374
          tmp_str.append(".");
 
2375
          tmp_str.append(sql_field->name);
 
2376
          tmp_str_lower= lower_string(tmp_str);
 
2377
          completion_map[tmp_str_lower]= tmp_str;
 
2378
 
 
2379
          tmp_str=sql_field->name;
 
2380
          tmp_str_lower= lower_string(tmp_str);
 
2381
          completion_map[tmp_str_lower]= tmp_str;
 
2382
 
2423
2383
        }
2424
2384
        drizzleclient_free_result(fields);
2425
2385
      }
2426
2386
    }
2427
 
    else
2428
 
      field_names[i]= 0;
2429
 
 
2430
 
    i++;
2431
2387
  }
2432
2388
  drizzleclient_free_result(tables);
2433
 
  field_names[i]=0;        // End pointer
2434
 
  return;
 
2389
  completion_iter= completion_map.begin();
2435
2390
}
2436
2391
 
2437
2392
/* for gnu readline */