~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/console/console.cc

Merged vcol stuff.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2009 Sun Microsystems, Inc.
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
 
 
16
 
#include "config.h"
17
 
#include <drizzled/gettext.h>
18
 
#include <drizzled/plugin/listen_tcp.h>
19
 
#include <drizzled/plugin/client.h>
20
 
#include <drizzled/session.h>
21
 
#include <drizzled/module/option_map.h>
22
 
 
23
 
#include <drizzled/plugin/catalog.h>
24
 
 
25
 
#include <iostream>
26
 
 
27
 
#include <boost/program_options.hpp>
28
 
 
29
 
using namespace std;
30
 
using namespace drizzled;
31
 
 
32
 
namespace po= boost::program_options;
33
 
 
34
 
static bool enabled= false;
35
 
static bool debug_enabled= false;
36
 
 
37
 
 
38
 
class ClientConsole: public plugin::Client
39
 
{
40
 
  bool is_dead;
41
 
  uint32_t column;
42
 
  uint32_t max_column;
43
 
  const std::string &username;
44
 
  const std::string &password;
45
 
  const std::string &schema;
46
 
  const std::string &_catalog;
47
 
 
48
 
public:
49
 
  ClientConsole(const std::string &username_arg,
50
 
                const std::string &password_arg,
51
 
                const std::string &schema_arg,
52
 
                const std::string &catalog_arg) :
53
 
    is_dead(false),
54
 
    column(0),
55
 
    max_column(0),
56
 
    username(username_arg),
57
 
    password(password_arg),
58
 
    schema(schema_arg),
59
 
    _catalog(catalog_arg)
60
 
  {}
61
 
 
62
 
  virtual void printDebug(const char *message)
63
 
  {
64
 
    if (debug_enabled)
65
 
      cout << "CONSOLE: " << message << endl;
66
 
  }
67
 
 
68
 
  catalog::Instance::shared_ptr catalog()
69
 
  {
70
 
    identifier::Catalog identifier(_catalog);
71
 
    catalog::Instance::shared_ptr tmp= plugin::Catalog::getInstance(identifier);
72
 
    if (not tmp)
73
 
    {
74
 
      std::cerr << "Invalid catalog '" << identifier << "', resorting to 'local' catalog" << std::endl;
75
 
    }
76
 
    return tmp;
77
 
  }
78
 
 
79
 
  virtual int getFileDescriptor(void)
80
 
  {
81
 
    printDebug("getFileDescriptor");
82
 
    return 0;
83
 
  }
84
 
 
85
 
  virtual bool isConnected(void)
86
 
  {
87
 
    printDebug("isConnected");
88
 
    return true;
89
 
  }
90
 
 
91
 
  virtual bool isReading(void)
92
 
  {
93
 
    printDebug("isReading");
94
 
    return false;
95
 
  }
96
 
 
97
 
  virtual bool isWriting(void)
98
 
  {
99
 
    printDebug("isWriting");
100
 
    return false;
101
 
  }
102
 
 
103
 
  virtual bool flush(void)
104
 
  {
105
 
    printDebug("flush");
106
 
    return false;
107
 
  }
108
 
 
109
 
  virtual void close(void)
110
 
  {
111
 
    printDebug("close");
112
 
    is_dead= true;
113
 
  }
114
 
 
115
 
  virtual bool authenticate(void)
116
 
  {
117
 
    printDebug("authenticate");
118
 
    identifier::User::shared_ptr user= identifier::User::make_shared();
119
 
    user->setUser(username);
120
 
    session->setUser(user);
121
 
 
122
 
    return session->checkUser(password, schema);
123
 
  }
124
 
 
125
 
  virtual bool readCommand(char **packet, uint32_t *packet_length)
126
 
  {
127
 
    uint32_t length;
128
 
 
129
 
    if (is_dead)
130
 
      return false;
131
 
 
132
 
    cout << "drizzled> ";
133
 
 
134
 
    length= 1024;
135
 
    *packet= NULL;
136
 
 
137
 
    /* Start with 1 byte offset so we can set command. */
138
 
    *packet_length= 1;
139
 
 
140
 
    do
141
 
    {
142
 
      *packet= (char *)realloc(*packet, length);
143
 
      if (*packet == NULL)
144
 
        return false;
145
 
 
146
 
      cin.clear();
147
 
      cin.getline(*packet + *packet_length, length - *packet_length, ';');
148
 
      *packet_length+= cin.gcount();
149
 
      length*= 2;
150
 
    }
151
 
    while (cin.eof() == false && cin.fail() == true);
152
 
 
153
 
    if ((*packet_length == 1 && cin.eof() == true) or
154
 
        not strncasecmp(*packet + 1, "quit", 4) or
155
 
        not strncasecmp(*packet + 1, "exit", 4) or
156
 
        not strncasecmp(*packet + 1, "shutdown", sizeof("shutdown") -1))
157
 
    {
158
 
      is_dead= true;
159
 
      *packet_length= 1;
160
 
      (*packet)[0]= COM_SHUTDOWN;
161
 
 
162
 
      return true;
163
 
    }
164
 
 
165
 
    /* Skip \r and \n for next time. */
166
 
    cin.ignore(2, '\n');
167
 
 
168
 
    (*packet)[0]= COM_QUERY;
169
 
 
170
 
    return true;
171
 
  }
172
 
 
173
 
  virtual void sendOK(void)
174
 
  {
175
 
    cout << "OK" << endl;
176
 
  }
177
 
 
178
 
  virtual void sendEOF(void)
179
 
  {
180
 
    printDebug("sendEOF");
181
 
  }
182
 
 
183
 
  virtual void sendError(const drizzled::error_t sql_errno, const char *err)
184
 
  {
185
 
    cout << "Error: " << static_cast<long>(sql_errno) << " " << err << endl;
186
 
  }
187
 
 
188
 
  virtual bool sendFields(List<Item> *list)
189
 
  {
190
 
    List_iterator_fast<Item> it(*list);
191
 
    Item *item;
192
 
 
193
 
    column= 0;
194
 
    max_column= 0;
195
 
 
196
 
    while ((item=it++))
197
 
    {
198
 
      SendField field;
199
 
      item->make_field(&field);
200
 
      cout << field.col_name << "\t";
201
 
      max_column++;
202
 
    }
203
 
 
204
 
    cout << endl;
205
 
 
206
 
    return false;
207
 
  }
208
 
 
209
 
  virtual void checkRowEnd(void)
210
 
  {
211
 
    if (++column % max_column == 0)
212
 
      cout << endl;
213
 
  }
214
 
 
215
 
  using Client::store;
216
 
 
217
 
  virtual bool store(Field *from)
218
 
  {
219
 
    if (from->is_null())
220
 
      return store();
221
 
 
222
 
    char buff[MAX_FIELD_WIDTH];
223
 
    String str(buff, sizeof(buff), &my_charset_bin);
224
 
    from->val_str_internal(&str);
225
 
    return store(str.ptr(), str.length());
226
 
  }
227
 
 
228
 
  virtual bool store(void)
229
 
  {
230
 
    cout << "NULL" << "\t";
231
 
    checkRowEnd();
232
 
    return false;
233
 
  }
234
 
 
235
 
  virtual bool store(int32_t from)
236
 
  {
237
 
    cout << from << "\t";
238
 
    checkRowEnd();
239
 
    return false;
240
 
  }
241
 
 
242
 
  virtual bool store(uint32_t from)
243
 
  {
244
 
    cout << from << "\t";
245
 
    checkRowEnd();
246
 
    return false;
247
 
  }
248
 
 
249
 
  virtual bool store(int64_t from)
250
 
  {
251
 
    cout << from << "\t";
252
 
    checkRowEnd();
253
 
    return false;
254
 
  }
255
 
 
256
 
  virtual bool store(uint64_t from)
257
 
  {
258
 
    cout << from << "\t";
259
 
    checkRowEnd();
260
 
    return false;
261
 
  }
262
 
 
263
 
  virtual bool store(double from, uint32_t decimals, String *buffer)
264
 
  {
265
 
    buffer->set_real(from, decimals, &my_charset_bin);
266
 
    return store(buffer->ptr(), buffer->length());
267
 
  }
268
 
 
269
 
  virtual bool store(const char *from, size_t length)
270
 
  {
271
 
    cout.write(from, length);
272
 
    cout << "\t";
273
 
    checkRowEnd();
274
 
    return false;
275
 
  }
276
 
 
277
 
  virtual bool haveMoreData(void)
278
 
  {
279
 
    printDebug("haveMoreData");
280
 
    return false;
281
 
  }
282
 
 
283
 
  virtual bool haveError(void)
284
 
  {
285
 
    printDebug("haveError");
286
 
    return false;
287
 
  }
288
 
 
289
 
  virtual bool wasAborted(void)
290
 
  {
291
 
    printDebug("wasAborted");
292
 
    return false;
293
 
  }
294
 
 
295
 
  bool isConsole()
296
 
  {
297
 
    return true;
298
 
  }
299
 
};
300
 
 
301
 
class ListenConsole: public plugin::Listen
302
 
{
303
 
  int pipe_fds[2];
304
 
  const std::string username;
305
 
  const std::string password;
306
 
  const std::string schema;
307
 
  const std::string _catalog;
308
 
 
309
 
public:
310
 
  ListenConsole(const std::string &name_arg,
311
 
                const std::string &username_arg,
312
 
                const std::string &password_arg,
313
 
                const std::string &schema_arg,
314
 
                const std::string &catalog_arg) :
315
 
    plugin::Listen(name_arg),
316
 
    username(username_arg),
317
 
    password(password_arg),
318
 
    schema(schema_arg),
319
 
    _catalog(catalog_arg)
320
 
  {
321
 
    pipe_fds[0]= -1;
322
 
  }
323
 
 
324
 
  virtual ~ListenConsole()
325
 
  {
326
 
    if (pipe_fds[0] != -1)
327
 
    {
328
 
      close(pipe_fds[0]);
329
 
      close(pipe_fds[1]);
330
 
    }
331
 
  }
332
 
 
333
 
  virtual bool getFileDescriptors(std::vector<int> &fds)
334
 
  {
335
 
    if (debug_enabled)
336
 
      enabled= true;
337
 
 
338
 
    if (not enabled)
339
 
      return false;
340
 
 
341
 
    if (pipe(pipe_fds) == -1)
342
 
    {
343
 
      errmsg_printf(error::ERROR, _("pipe() failed with errno %d"), errno);
344
 
      return true;
345
 
    }
346
 
 
347
 
    fds.push_back(pipe_fds[0]);
348
 
    assert(write(pipe_fds[1], "\0", 1) == 1);
349
 
    return false;
350
 
  }
351
 
 
352
 
  virtual drizzled::plugin::Client *getClient(int fd)
353
 
  {
354
 
    char buffer[1];
355
 
    assert(read(fd, buffer, 1) == 1);
356
 
 
357
 
    return new ClientConsole(username, password, schema, _catalog);
358
 
  }
359
 
};
360
 
 
361
 
static int init(drizzled::module::Context &context)
362
 
{
363
 
  const module::option_map &vm= context.getOptions();
364
 
  const string username(vm.count("username") ? vm["username"].as<string>() : "");
365
 
  const string password(vm.count("password") ? vm["password"].as<string>() : "");
366
 
  const string schema(vm.count("schema") ? vm["schema"].as<string>() : "");
367
 
 
368
 
  const std::string catalog(vm.count("catalog") ? vm["catalog"].as<string>() : "LOCAL");
369
 
 
370
 
  context.add(new ListenConsole("console", username, password, schema, catalog));
371
 
 
372
 
  return 0;
373
 
}
374
 
 
375
 
static void init_options(drizzled::module::option_context &context)
376
 
{
377
 
  context("enable",
378
 
          po::value<bool>(&enabled)->default_value(false)->zero_tokens(),
379
 
          N_("Enable the console."));
380
 
  context("debug",
381
 
          po::value<bool>(&debug_enabled)->default_value(false)->zero_tokens(),
382
 
          N_("Turn on extra debugging."));
383
 
  context("username",
384
 
          po::value<string>(),
385
 
          N_("User to use for auth."));
386
 
  context("password",
387
 
          po::value<string>(),
388
 
          N_("Password to use for auth."));
389
 
  context("catalog",
390
 
          po::value<string>(),
391
 
          N_("Default catalog to use."));
392
 
  context("schema",
393
 
          po::value<string>(),
394
 
          N_("Default schema to use."));
395
 
}
396
 
 
397
 
DRIZZLE_DECLARE_PLUGIN
398
 
{
399
 
  DRIZZLE_VERSION_ID,
400
 
  "console",
401
 
  "0.2",
402
 
  "Eric Day",
403
 
  "Console Client",
404
 
  PLUGIN_LICENSE_BSD,
405
 
  init,   /* Plugin Init */
406
 
  NULL,   /* depends */
407
 
  init_options    /* config options */
408
 
}
409
 
DRIZZLE_DECLARE_PLUGIN_END;