1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 MySQL
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
/* drizzle command tool
22
* Commands compatible with mSQL by David J. Hughes
25
* Michael 'Monty' Widenius
26
* Andi Gutmans <andi@zend.com>
27
* Zeev Suraski <zeev@zend.com>
28
* Jani Tolonen <jani@mysql.com>
29
* Matt Wagner <matt@mysql.com>
30
* Jeremy Cole <jcole@mysql.com>
31
* Tonu Samuel <tonu@mysql.com>
32
* Harrison Fisk <harrison@mysql.com>
36
#include "client_priv.h"
38
#include <drizzled/gettext.h>
44
#include "drizzled/charset_info.h"
47
#include "client/linebuffer.h"
49
#include <sys/ioctl.h>
50
#include <drizzled/configmake.h>
51
#include "drizzled/charset.h"
53
#if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
61
#if defined(HAVE_TERMIOS_H)
64
#elif defined(HAVE_TERMBITS_H)
66
#elif defined(HAVE_ASM_TERMBITS_H) && (!defined __GLIBC__ || !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
67
#include <asm/termbits.h> // Standard linux
69
#if defined(HAVE_TERMCAP_H)
75
#undef SYSV // hack to avoid syntax error
82
#ifdef HAVE_LIBREADLINE
83
# if defined(HAVE_READLINE_READLINE_H)
84
# include <readline/readline.h>
85
# elif defined(HAVE_READLINE_H)
86
# include <readline.h>
87
# else /* !defined(HAVE_READLINE_H) */
88
extern char *readline ();
89
# endif /* !defined(HAVE_READLINE_H) */
91
#else /* !defined(HAVE_READLINE_READLINE_H) */
93
# error Readline Required
94
#endif /* HAVE_LIBREADLINE */
96
#ifdef HAVE_READLINE_HISTORY
97
# if defined(HAVE_READLINE_HISTORY_H)
98
# include <readline/history.h>
99
# elif defined(HAVE_HISTORY_H)
100
# include <history.h>
101
# else /* !defined(HAVE_HISTORY_H) */
102
extern void add_history ();
103
extern int write_history ();
104
extern int read_history ();
105
# endif /* defined(HAVE_READLINE_HISTORY_H) */
107
#endif /* HAVE_READLINE_HISTORY */
110
Make the old readline interface look like the new one.
112
#ifndef HAVE_RL_COMPLETION
113
typedef char **rl_completion_func_t(const char *, int, int);
114
#define rl_completion_matches(str, func) \
115
completion_matches((char *)str, (CPFunction *)func)
118
#ifdef HAVE_RL_COMPENTRY
119
# ifdef HAVE_WORKING_RL_COMPENTRY
120
typedef rl_compentry_func_t drizzle_compentry_func_t;
122
/* Snow Leopard ships an rl_compentry which cannot be assigned to
123
* rl_completion_entry_function. We must undo the complete and total
126
typedef Function drizzle_compentry_func_t;
129
typedef Function drizzle_compentry_func_t;
132
#if defined(HAVE_LOCALE_H)
138
#if !defined(HAVE_VIDATTR)
140
#define vidattr(A) {} // Can't get this to work
143
using namespace drizzled;
146
const string VER("14.14");
147
/* Don't try to make a nice table if the data is too big */
148
const uint32_t MAX_COLUMN_LENGTH= 1024;
150
/* Buffer to hold 'version' and 'version_comment' */
151
const int MAX_SERVER_VERSION_LENGTH= 128;
153
#define PROMPT_CHAR '\\'
154
#define DEFAULT_DELIMITER ";"
156
typedef struct st_status
159
uint32_t query_start_line;
161
LineBuffer *line_buff;
162
bool batch,add_to_history;
166
static map<string, string>::iterator completion_iter;
167
static map<string, string>::iterator completion_end;
168
static map<string, string> completion_map;
169
static string completion_string;
171
static char **defaults_argv;
173
enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
174
typedef enum enum_info_type INFO_TYPE;
176
static drizzle_st drizzle; /* The library handle */
177
static drizzle_con_st con; /* The connection */
178
static bool ignore_errors= false, quick= false,
179
connected= false, opt_raw_data= false, unbuffered= false,
180
output_tables= false, opt_rehash= true, skip_updates= false,
181
safe_updates= false, one_database= false,
182
opt_compress= false, opt_shutdown= false, opt_ping= false,
183
vertical= false, line_numbers= true, column_names= true,
184
opt_nopager= true, opt_outfile= false, named_cmds= false,
185
tty_password= false, opt_nobeep= false, opt_reconnect= true,
186
default_charset_used= false, opt_secure_auth= false,
187
default_pager_set= false, opt_sigint_ignore= false,
188
auto_vertical_output= false,
189
show_warnings= false, executing_query= false, interrupted_query= false,
191
static uint32_t show_progress_size= 0;
192
static bool column_types_flag;
193
static bool preserve_comments= false;
194
static uint32_t opt_max_input_line, opt_drizzle_port= 0;
195
static int verbose= 0, opt_silent= 0, opt_local_infile= 0;
196
static drizzle_capabilities_t connect_flag= DRIZZLE_CAPABILITIES_NONE;
197
static char *current_host, *current_db, *current_user= NULL,
198
*opt_password= NULL, *delimiter_str= NULL, *current_prompt= NULL;
199
static char *histfile;
200
static char *histfile_tmp;
201
static string *glob_buffer;
202
static string *processed_prompt= NULL;
203
static char *default_prompt= NULL;
204
static char *full_username= NULL,*part_username= NULL;
205
static STATUS status;
206
static uint32_t select_limit;
207
static uint32_t max_join_size;
208
static uint32_t opt_connect_timeout= 0;
209
// TODO: Need to i18n these
210
static const char *day_names[]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
211
static const char *month_names[]= {"Jan","Feb","Mar","Apr","May","Jun","Jul",
212
"Aug","Sep","Oct","Nov","Dec"};
213
static char default_pager[FN_REFLEN];
214
static char pager[FN_REFLEN], outfile[FN_REFLEN];
215
static FILE *PAGER, *OUTFILE;
216
static uint32_t prompt_counter;
217
static char delimiter[16]= DEFAULT_DELIMITER;
218
static uint32_t delimiter_length= 1;
219
unsigned short terminal_width= 80;
221
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
223
int drizzleclient_real_query_for_lazy(const char *buf, int length,
224
drizzle_result_st *result,
225
uint32_t *error_code);
226
int drizzleclient_store_result_for_lazy(drizzle_result_st *result);
229
void tee_fprintf(FILE *file, const char *fmt, ...);
230
void tee_fputs(const char *s, FILE *file);
231
void tee_puts(const char *s, FILE *file);
232
void tee_putc(int c, FILE *file);
233
static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
234
/* The names of functions that actually do the manipulation. */
235
static int get_options(int argc,char **argv);
236
static int com_quit(string *str,const char*),
237
com_go(string *str,const char*), com_ego(string *str,const char*),
238
com_print(string *str,const char*),
239
com_help(string *str,const char*), com_clear(string *str,const char*),
240
com_connect(string *str,const char*), com_status(string *str,const char*),
241
com_use(string *str,const char*), com_source(string *str, const char*),
242
com_rehash(string *str, const char*), com_tee(string *str, const char*),
243
com_notee(string *str, const char*),
244
com_prompt(string *str, const char*), com_delimiter(string *str, const char*),
245
com_warnings(string *str, const char*), com_nowarnings(string *str, const char*),
246
com_nopager(string *str, const char*), com_pager(string *str, const char*);
248
static int read_and_execute(bool interactive);
249
static int sql_connect(char *host,char *database,char *user,char *password,
251
static const char *server_version_string(drizzle_con_st *con);
252
static int put_info(const char *str,INFO_TYPE info,uint32_t error,
253
const char *sql_state);
254
static int put_error(drizzle_con_st *con, drizzle_result_st *res);
255
static void safe_put_field(const char *pos,uint32_t length);
256
static void init_pager(void);
257
static void end_pager(void);
258
static void init_tee(const char *);
259
static void end_tee(void);
260
static const char* construct_prompt(void);
261
static char *get_arg(char *line, bool get_next_arg);
262
static void init_username(void);
263
static void add_int_to_prompt(int toadd);
264
static int get_result_width(drizzle_result_st *res);
265
static int get_field_disp_length(drizzle_column_st * field);
266
static const char * strcont(register const char *str, register const char *set);
268
/* A structure which contains information on the commands this program
271
const char *name; /* User printable name of the function. */
272
char cmd_char; /* msql command character */
273
int (*func)(string *str,const char *); /* Function to call to do the job. */
274
bool takes_params; /* Max parameters for command */
275
const char *doc; /* Documentation for this function. */
279
static COMMANDS commands[] = {
280
{ "?", '?', com_help, 0, N_("Synonym for `help'.") },
281
{ "clear", 'c', com_clear, 0, N_("Clear command.")},
282
{ "connect",'r', com_connect,1,
283
N_("Reconnect to the server. Optional arguments are db and host.")},
284
{ "delimiter", 'd', com_delimiter, 1,
285
N_("Set statement delimiter. NOTE: Takes the rest of the line as new delimiter.") },
286
{ "ego", 'G', com_ego, 0,
287
N_("Send command to drizzle server, display result vertically.")},
288
{ "exit", 'q', com_quit, 0, N_("Exit drizzle. Same as quit.")},
289
{ "go", 'g', com_go, 0, N_("Send command to drizzle server.") },
290
{ "help", 'h', com_help, 0, N_("Display this help.") },
291
{ "nopager",'n', com_nopager,0, N_("Disable pager, print to stdout.") },
292
{ "notee", 't', com_notee, 0, N_("Don't write into outfile.") },
293
{ "pager", 'P', com_pager, 1,
294
N_("Set PAGER [to_pager]. Print the query results via PAGER.") },
295
{ "print", 'p', com_print, 0, N_("Print current command.") },
296
{ "prompt", 'R', com_prompt, 1, N_("Change your drizzle prompt.")},
297
{ "quit", 'q', com_quit, 0, N_("Quit drizzle.") },
298
{ "rehash", '#', com_rehash, 0, N_("Rebuild completion hash.") },
299
{ "source", '.', com_source, 1,
300
N_("Execute an SQL script file. Takes a file name as an argument.")},
301
{ "status", 's', com_status, 0, N_("Get status information from the server.")},
302
{ "tee", 'T', com_tee, 1,
303
N_("Set outfile [to_outfile]. Append everything into given outfile.") },
304
{ "use", 'u', com_use, 1,
305
N_("Use another database. Takes database name as argument.") },
306
{ "warnings", 'W', com_warnings, 0,
307
N_("Show warnings after every statement.") },
308
{ "nowarning", 'w', com_nowarnings, 0,
309
N_("Don't show warnings after every statement.") },
310
/* Get bash-like expansion for some commands */
311
{ "create table", 0, 0, 0, ""},
312
{ "create database", 0, 0, 0, ""},
313
{ "show databases", 0, 0, 0, ""},
314
{ "show fields from", 0, 0, 0, ""},
315
{ "show keys from", 0, 0, 0, ""},
316
{ "show tables", 0, 0, 0, ""},
317
{ "load data from", 0, 0, 0, ""},
318
{ "alter table", 0, 0, 0, ""},
319
{ "set option", 0, 0, 0, ""},
320
{ "lock tables", 0, 0, 0, ""},
321
{ "unlock tables", 0, 0, 0, ""},
322
/* generated 2006-12-28. Refresh occasionally from lexer. */
323
{ "ACTION", 0, 0, 0, ""},
324
{ "ADD", 0, 0, 0, ""},
325
{ "AFTER", 0, 0, 0, ""},
326
{ "AGAINST", 0, 0, 0, ""},
327
{ "AGGREGATE", 0, 0, 0, ""},
328
{ "ALL", 0, 0, 0, ""},
329
{ "ALGORITHM", 0, 0, 0, ""},
330
{ "ALTER", 0, 0, 0, ""},
331
{ "ANALYZE", 0, 0, 0, ""},
332
{ "AND", 0, 0, 0, ""},
333
{ "ANY", 0, 0, 0, ""},
334
{ "AS", 0, 0, 0, ""},
335
{ "ASC", 0, 0, 0, ""},
336
{ "ASCII", 0, 0, 0, ""},
337
{ "ASENSITIVE", 0, 0, 0, ""},
338
{ "AUTO_INCREMENT", 0, 0, 0, ""},
339
{ "AVG", 0, 0, 0, ""},
340
{ "AVG_ROW_LENGTH", 0, 0, 0, ""},
341
{ "BACKUP", 0, 0, 0, ""},
342
{ "BDB", 0, 0, 0, ""},
343
{ "BEFORE", 0, 0, 0, ""},
344
{ "BEGIN", 0, 0, 0, ""},
345
{ "BERKELEYDB", 0, 0, 0, ""},
346
{ "BETWEEN", 0, 0, 0, ""},
347
{ "BIGINT", 0, 0, 0, ""},
348
{ "BINARY", 0, 0, 0, ""},
349
{ "BINLOG", 0, 0, 0, ""},
350
{ "BIT", 0, 0, 0, ""},
351
{ "BLOB", 0, 0, 0, ""},
352
{ "BOOL", 0, 0, 0, ""},
353
{ "BOOLEAN", 0, 0, 0, ""},
354
{ "BOTH", 0, 0, 0, ""},
355
{ "BTREE", 0, 0, 0, ""},
356
{ "BY", 0, 0, 0, ""},
357
{ "BYTE", 0, 0, 0, ""},
358
{ "CACHE", 0, 0, 0, ""},
359
{ "CALL", 0, 0, 0, ""},
360
{ "CASCADE", 0, 0, 0, ""},
361
{ "CASCADED", 0, 0, 0, ""},
362
{ "CASE", 0, 0, 0, ""},
363
{ "CHAIN", 0, 0, 0, ""},
364
{ "CHANGE", 0, 0, 0, ""},
365
{ "CHANGED", 0, 0, 0, ""},
366
{ "CHAR", 0, 0, 0, ""},
367
{ "CHARACTER", 0, 0, 0, ""},
368
{ "CHARSET", 0, 0, 0, ""},
369
{ "CHECK", 0, 0, 0, ""},
370
{ "CHECKSUM", 0, 0, 0, ""},
371
{ "CIPHER", 0, 0, 0, ""},
372
{ "CLIENT", 0, 0, 0, ""},
373
{ "CLOSE", 0, 0, 0, ""},
374
{ "CODE", 0, 0, 0, ""},
375
{ "COLLATE", 0, 0, 0, ""},
376
{ "COLLATION", 0, 0, 0, ""},
377
{ "COLUMN", 0, 0, 0, ""},
378
{ "COLUMNS", 0, 0, 0, ""},
379
{ "COMMENT", 0, 0, 0, ""},
380
{ "COMMIT", 0, 0, 0, ""},
381
{ "COMMITTED", 0, 0, 0, ""},
382
{ "COMPACT", 0, 0, 0, ""},
383
{ "COMPRESSED", 0, 0, 0, ""},
384
{ "CONCURRENT", 0, 0, 0, ""},
385
{ "CONDITION", 0, 0, 0, ""},
386
{ "CONNECTION", 0, 0, 0, ""},
387
{ "CONSISTENT", 0, 0, 0, ""},
388
{ "CONSTRAINT", 0, 0, 0, ""},
389
{ "CONTAINS", 0, 0, 0, ""},
390
{ "CONTINUE", 0, 0, 0, ""},
391
{ "CONVERT", 0, 0, 0, ""},
392
{ "CREATE", 0, 0, 0, ""},
393
{ "CROSS", 0, 0, 0, ""},
394
{ "CUBE", 0, 0, 0, ""},
395
{ "CURRENT_DATE", 0, 0, 0, ""},
396
{ "CURRENT_TIMESTAMP", 0, 0, 0, ""},
397
{ "CURRENT_USER", 0, 0, 0, ""},
398
{ "CURSOR", 0, 0, 0, ""},
399
{ "DATA", 0, 0, 0, ""},
400
{ "DATABASE", 0, 0, 0, ""},
401
{ "DATABASES", 0, 0, 0, ""},
402
{ "DATE", 0, 0, 0, ""},
403
{ "DATETIME", 0, 0, 0, ""},
404
{ "DAY", 0, 0, 0, ""},
405
{ "DAY_HOUR", 0, 0, 0, ""},
406
{ "DAY_MICROSECOND", 0, 0, 0, ""},
407
{ "DAY_MINUTE", 0, 0, 0, ""},
408
{ "DAY_SECOND", 0, 0, 0, ""},
409
{ "DEALLOCATE", 0, 0, 0, ""},
410
{ "DEC", 0, 0, 0, ""},
411
{ "DECIMAL", 0, 0, 0, ""},
412
{ "DECLARE", 0, 0, 0, ""},
413
{ "DEFAULT", 0, 0, 0, ""},
414
{ "DEFINER", 0, 0, 0, ""},
415
{ "DELAYED", 0, 0, 0, ""},
416
{ "DELAY_KEY_WRITE", 0, 0, 0, ""},
417
{ "DELETE", 0, 0, 0, ""},
418
{ "DESC", 0, 0, 0, ""},
419
{ "DESCRIBE", 0, 0, 0, ""},
420
{ "DES_KEY_FILE", 0, 0, 0, ""},
421
{ "DETERMINISTIC", 0, 0, 0, ""},
422
{ "DIRECTORY", 0, 0, 0, ""},
423
{ "DISABLE", 0, 0, 0, ""},
424
{ "DISCARD", 0, 0, 0, ""},
425
{ "DISTINCT", 0, 0, 0, ""},
426
{ "DISTINCTROW", 0, 0, 0, ""},
427
{ "DIV", 0, 0, 0, ""},
428
{ "DO", 0, 0, 0, ""},
429
{ "DOUBLE", 0, 0, 0, ""},
430
{ "DROP", 0, 0, 0, ""},
431
{ "DUAL", 0, 0, 0, ""},
432
{ "DUMPFILE", 0, 0, 0, ""},
433
{ "DUPLICATE", 0, 0, 0, ""},
434
{ "DYNAMIC", 0, 0, 0, ""},
435
{ "EACH", 0, 0, 0, ""},
436
{ "ELSE", 0, 0, 0, ""},
437
{ "ELSEIF", 0, 0, 0, ""},
438
{ "ENABLE", 0, 0, 0, ""},
439
{ "ENCLOSED", 0, 0, 0, ""},
440
{ "END", 0, 0, 0, ""},
441
{ "ENGINE", 0, 0, 0, ""},
442
{ "ENGINES", 0, 0, 0, ""},
443
{ "ENUM", 0, 0, 0, ""},
444
{ "ERRORS", 0, 0, 0, ""},
445
{ "ESCAPE", 0, 0, 0, ""},
446
{ "ESCAPED", 0, 0, 0, ""},
447
{ "EVENTS", 0, 0, 0, ""},
448
{ "EXECUTE", 0, 0, 0, ""},
449
{ "EXISTS", 0, 0, 0, ""},
450
{ "EXIT", 0, 0, 0, ""},
451
{ "EXPANSION", 0, 0, 0, ""},
452
{ "EXPLAIN", 0, 0, 0, ""},
453
{ "EXTENDED", 0, 0, 0, ""},
454
{ "FALSE", 0, 0, 0, ""},
455
{ "FAST", 0, 0, 0, ""},
456
{ "FETCH", 0, 0, 0, ""},
457
{ "FIELDS", 0, 0, 0, ""},
458
{ "FILE", 0, 0, 0, ""},
459
{ "FIRST", 0, 0, 0, ""},
460
{ "FIXED", 0, 0, 0, ""},
461
{ "FLOAT", 0, 0, 0, ""},
462
{ "FLOAT4", 0, 0, 0, ""},
463
{ "FLOAT8", 0, 0, 0, ""},
464
{ "FLUSH", 0, 0, 0, ""},
465
{ "FOR", 0, 0, 0, ""},
466
{ "FORCE", 0, 0, 0, ""},
467
{ "FOREIGN", 0, 0, 0, ""},
468
{ "FOUND", 0, 0, 0, ""},
469
{ "FRAC_SECOND", 0, 0, 0, ""},
470
{ "FROM", 0, 0, 0, ""},
471
{ "FULL", 0, 0, 0, ""},
472
{ "FULLTEXT", 0, 0, 0, ""},
473
{ "FUNCTION", 0, 0, 0, ""},
474
{ "GLOBAL", 0, 0, 0, ""},
475
{ "GRANT", 0, 0, 0, ""},
476
{ "GRANTS", 0, 0, 0, ""},
477
{ "GROUP", 0, 0, 0, ""},
478
{ "HANDLER", 0, 0, 0, ""},
479
{ "HASH", 0, 0, 0, ""},
480
{ "HAVING", 0, 0, 0, ""},
481
{ "HELP", 0, 0, 0, ""},
482
{ "HIGH_PRIORITY", 0, 0, 0, ""},
483
{ "HOSTS", 0, 0, 0, ""},
484
{ "HOUR", 0, 0, 0, ""},
485
{ "HOUR_MICROSECOND", 0, 0, 0, ""},
486
{ "HOUR_MINUTE", 0, 0, 0, ""},
487
{ "HOUR_SECOND", 0, 0, 0, ""},
488
{ "IDENTIFIED", 0, 0, 0, ""},
489
{ "IF", 0, 0, 0, ""},
490
{ "IGNORE", 0, 0, 0, ""},
491
{ "IMPORT", 0, 0, 0, ""},
492
{ "IN", 0, 0, 0, ""},
493
{ "INDEX", 0, 0, 0, ""},
494
{ "INDEXES", 0, 0, 0, ""},
495
{ "INFILE", 0, 0, 0, ""},
496
{ "INNER", 0, 0, 0, ""},
497
{ "INNOBASE", 0, 0, 0, ""},
498
{ "INNODB", 0, 0, 0, ""},
499
{ "INOUT", 0, 0, 0, ""},
500
{ "INSENSITIVE", 0, 0, 0, ""},
501
{ "INSERT", 0, 0, 0, ""},
502
{ "INSERT_METHOD", 0, 0, 0, ""},
503
{ "INT", 0, 0, 0, ""},
504
{ "INT1", 0, 0, 0, ""},
505
{ "INT2", 0, 0, 0, ""},
506
{ "INT3", 0, 0, 0, ""},
507
{ "INT4", 0, 0, 0, ""},
508
{ "INT8", 0, 0, 0, ""},
509
{ "INTEGER", 0, 0, 0, ""},
510
{ "INTERVAL", 0, 0, 0, ""},
511
{ "INTO", 0, 0, 0, ""},
512
{ "IO_THREAD", 0, 0, 0, ""},
513
{ "IS", 0, 0, 0, ""},
514
{ "ISOLATION", 0, 0, 0, ""},
515
{ "ISSUER", 0, 0, 0, ""},
516
{ "ITERATE", 0, 0, 0, ""},
517
{ "INVOKER", 0, 0, 0, ""},
518
{ "JOIN", 0, 0, 0, ""},
519
{ "KEY", 0, 0, 0, ""},
520
{ "KEYS", 0, 0, 0, ""},
521
{ "KILL", 0, 0, 0, ""},
522
{ "LANGUAGE", 0, 0, 0, ""},
523
{ "LAST", 0, 0, 0, ""},
524
{ "LEADING", 0, 0, 0, ""},
525
{ "LEAVE", 0, 0, 0, ""},
526
{ "LEAVES", 0, 0, 0, ""},
527
{ "LEFT", 0, 0, 0, ""},
528
{ "LEVEL", 0, 0, 0, ""},
529
{ "LIKE", 0, 0, 0, ""},
530
{ "LIMIT", 0, 0, 0, ""},
531
{ "LINES", 0, 0, 0, ""},
532
{ "LINESTRING", 0, 0, 0, ""},
533
{ "LOAD", 0, 0, 0, ""},
534
{ "LOCAL", 0, 0, 0, ""},
535
{ "LOCALTIMESTAMP", 0, 0, 0, ""},
536
{ "LOCK", 0, 0, 0, ""},
537
{ "LOCKS", 0, 0, 0, ""},
538
{ "LOGS", 0, 0, 0, ""},
539
{ "LONG", 0, 0, 0, ""},
540
{ "LONGTEXT", 0, 0, 0, ""},
541
{ "LOOP", 0, 0, 0, ""},
542
{ "LOW_PRIORITY", 0, 0, 0, ""},
543
{ "MASTER", 0, 0, 0, ""},
544
{ "MASTER_CONNECT_RETRY", 0, 0, 0, ""},
545
{ "MASTER_HOST", 0, 0, 0, ""},
546
{ "MASTER_LOG_FILE", 0, 0, 0, ""},
547
{ "MASTER_LOG_POS", 0, 0, 0, ""},
548
{ "MASTER_PASSWORD", 0, 0, 0, ""},
549
{ "MASTER_PORT", 0, 0, 0, ""},
550
{ "MASTER_SERVER_ID", 0, 0, 0, ""},
551
{ "MASTER_SSL", 0, 0, 0, ""},
552
{ "MASTER_SSL_CA", 0, 0, 0, ""},
553
{ "MASTER_SSL_CAPATH", 0, 0, 0, ""},
554
{ "MASTER_SSL_CERT", 0, 0, 0, ""},
555
{ "MASTER_SSL_CIPHER", 0, 0, 0, ""},
556
{ "MASTER_SSL_KEY", 0, 0, 0, ""},
557
{ "MASTER_USER", 0, 0, 0, ""},
558
{ "MATCH", 0, 0, 0, ""},
559
{ "MAX_CONNECTIONS_PER_HOUR", 0, 0, 0, ""},
560
{ "MAX_QUERIES_PER_HOUR", 0, 0, 0, ""},
561
{ "MAX_ROWS", 0, 0, 0, ""},
562
{ "MAX_UPDATES_PER_HOUR", 0, 0, 0, ""},
563
{ "MAX_USER_CONNECTIONS", 0, 0, 0, ""},
564
{ "MEDIUM", 0, 0, 0, ""},
565
{ "MEDIUMTEXT", 0, 0, 0, ""},
566
{ "MERGE", 0, 0, 0, ""},
567
{ "MICROSECOND", 0, 0, 0, ""},
568
{ "MIDDLEINT", 0, 0, 0, ""},
569
{ "MIGRATE", 0, 0, 0, ""},
570
{ "MINUTE", 0, 0, 0, ""},
571
{ "MINUTE_MICROSECOND", 0, 0, 0, ""},
572
{ "MINUTE_SECOND", 0, 0, 0, ""},
573
{ "MIN_ROWS", 0, 0, 0, ""},
574
{ "MOD", 0, 0, 0, ""},
575
{ "MODE", 0, 0, 0, ""},
576
{ "MODIFIES", 0, 0, 0, ""},
577
{ "MODIFY", 0, 0, 0, ""},
578
{ "MONTH", 0, 0, 0, ""},
579
{ "MULTILINESTRING", 0, 0, 0, ""},
580
{ "MULTIPOINT", 0, 0, 0, ""},
581
{ "MULTIPOLYGON", 0, 0, 0, ""},
582
{ "MUTEX", 0, 0, 0, ""},
583
{ "NAME", 0, 0, 0, ""},
584
{ "NAMES", 0, 0, 0, ""},
585
{ "NATIONAL", 0, 0, 0, ""},
586
{ "NATURAL", 0, 0, 0, ""},
587
{ "NDB", 0, 0, 0, ""},
588
{ "NDBCLUSTER", 0, 0, 0, ""},
589
{ "NCHAR", 0, 0, 0, ""},
590
{ "NEW", 0, 0, 0, ""},
591
{ "NEXT", 0, 0, 0, ""},
592
{ "NO", 0, 0, 0, ""},
593
{ "NONE", 0, 0, 0, ""},
594
{ "NOT", 0, 0, 0, ""},
595
{ "NO_WRITE_TO_BINLOG", 0, 0, 0, ""},
596
{ "NULL", 0, 0, 0, ""},
597
{ "NUMERIC", 0, 0, 0, ""},
598
{ "NVARCHAR", 0, 0, 0, ""},
599
{ "OFFSET", 0, 0, 0, ""},
600
{ "OLD_PASSWORD", 0, 0, 0, ""},
601
{ "ON", 0, 0, 0, ""},
602
{ "ONE", 0, 0, 0, ""},
603
{ "ONE_SHOT", 0, 0, 0, ""},
604
{ "OPEN", 0, 0, 0, ""},
605
{ "OPTIMIZE", 0, 0, 0, ""},
606
{ "OPTION", 0, 0, 0, ""},
607
{ "OPTIONALLY", 0, 0, 0, ""},
608
{ "OR", 0, 0, 0, ""},
609
{ "ORDER", 0, 0, 0, ""},
610
{ "OUT", 0, 0, 0, ""},
611
{ "OUTER", 0, 0, 0, ""},
612
{ "OUTFILE", 0, 0, 0, ""},
613
{ "PACK_KEYS", 0, 0, 0, ""},
614
{ "PARTIAL", 0, 0, 0, ""},
615
{ "PASSWORD", 0, 0, 0, ""},
616
{ "PHASE", 0, 0, 0, ""},
617
{ "POINT", 0, 0, 0, ""},
618
{ "POLYGON", 0, 0, 0, ""},
619
{ "PRECISION", 0, 0, 0, ""},
620
{ "PREPARE", 0, 0, 0, ""},
621
{ "PREV", 0, 0, 0, ""},
622
{ "PRIMARY", 0, 0, 0, ""},
623
{ "PRIVILEGES", 0, 0, 0, ""},
624
{ "PROCEDURE", 0, 0, 0, ""},
625
{ "PROCESS", 0, 0, 0, ""},
626
{ "PROCESSLIST", 0, 0, 0, ""},
627
{ "PURGE", 0, 0, 0, ""},
628
{ "QUARTER", 0, 0, 0, ""},
629
{ "QUERY", 0, 0, 0, ""},
630
{ "QUICK", 0, 0, 0, ""},
631
{ "READ", 0, 0, 0, ""},
632
{ "READS", 0, 0, 0, ""},
633
{ "REAL", 0, 0, 0, ""},
634
{ "RECOVER", 0, 0, 0, ""},
635
{ "REDUNDANT", 0, 0, 0, ""},
636
{ "REFERENCES", 0, 0, 0, ""},
637
{ "REGEXP", 0, 0, 0, ""},
638
{ "RELAY_LOG_FILE", 0, 0, 0, ""},
639
{ "RELAY_LOG_POS", 0, 0, 0, ""},
640
{ "RELAY_THREAD", 0, 0, 0, ""},
641
{ "RELEASE", 0, 0, 0, ""},
642
{ "RELOAD", 0, 0, 0, ""},
643
{ "RENAME", 0, 0, 0, ""},
644
{ "REPAIR", 0, 0, 0, ""},
645
{ "REPEATABLE", 0, 0, 0, ""},
646
{ "REPLACE", 0, 0, 0, ""},
647
{ "REPLICATION", 0, 0, 0, ""},
648
{ "REPEAT", 0, 0, 0, ""},
649
{ "REQUIRE", 0, 0, 0, ""},
650
{ "RESET", 0, 0, 0, ""},
651
{ "RESTORE", 0, 0, 0, ""},
652
{ "RESTRICT", 0, 0, 0, ""},
653
{ "RESUME", 0, 0, 0, ""},
654
{ "RETURN", 0, 0, 0, ""},
655
{ "RETURNS", 0, 0, 0, ""},
656
{ "REVOKE", 0, 0, 0, ""},
657
{ "RIGHT", 0, 0, 0, ""},
658
{ "RLIKE", 0, 0, 0, ""},
659
{ "ROLLBACK", 0, 0, 0, ""},
660
{ "ROLLUP", 0, 0, 0, ""},
661
{ "ROUTINE", 0, 0, 0, ""},
662
{ "ROW", 0, 0, 0, ""},
663
{ "ROWS", 0, 0, 0, ""},
664
{ "ROW_FORMAT", 0, 0, 0, ""},
665
{ "RTREE", 0, 0, 0, ""},
666
{ "SAVEPOINT", 0, 0, 0, ""},
667
{ "SCHEMA", 0, 0, 0, ""},
668
{ "SCHEMAS", 0, 0, 0, ""},
669
{ "SECOND", 0, 0, 0, ""},
670
{ "SECOND_MICROSECOND", 0, 0, 0, ""},
671
{ "SECURITY", 0, 0, 0, ""},
672
{ "SELECT", 0, 0, 0, ""},
673
{ "SENSITIVE", 0, 0, 0, ""},
674
{ "SEPARATOR", 0, 0, 0, ""},
675
{ "SERIAL", 0, 0, 0, ""},
676
{ "SERIALIZABLE", 0, 0, 0, ""},
677
{ "SESSION", 0, 0, 0, ""},
678
{ "SET", 0, 0, 0, ""},
679
{ "SHARE", 0, 0, 0, ""},
680
{ "SHOW", 0, 0, 0, ""},
681
{ "SHUTDOWN", 0, 0, 0, ""},
682
{ "SIGNED", 0, 0, 0, ""},
683
{ "SIMPLE", 0, 0, 0, ""},
684
{ "SLAVE", 0, 0, 0, ""},
685
{ "SNAPSHOT", 0, 0, 0, ""},
686
{ "SMALLINT", 0, 0, 0, ""},
687
{ "SOME", 0, 0, 0, ""},
688
{ "SONAME", 0, 0, 0, ""},
689
{ "SOUNDS", 0, 0, 0, ""},
690
{ "SPATIAL", 0, 0, 0, ""},
691
{ "SPECIFIC", 0, 0, 0, ""},
692
{ "SQL", 0, 0, 0, ""},
693
{ "SQLEXCEPTION", 0, 0, 0, ""},
694
{ "SQLSTATE", 0, 0, 0, ""},
695
{ "SQLWARNING", 0, 0, 0, ""},
696
{ "SQL_BIG_RESULT", 0, 0, 0, ""},
697
{ "SQL_BUFFER_RESULT", 0, 0, 0, ""},
698
{ "SQL_CACHE", 0, 0, 0, ""},
699
{ "SQL_CALC_FOUND_ROWS", 0, 0, 0, ""},
700
{ "SQL_NO_CACHE", 0, 0, 0, ""},
701
{ "SQL_SMALL_RESULT", 0, 0, 0, ""},
702
{ "SQL_THREAD", 0, 0, 0, ""},
703
{ "SQL_TSI_FRAC_SECOND", 0, 0, 0, ""},
704
{ "SQL_TSI_SECOND", 0, 0, 0, ""},
705
{ "SQL_TSI_MINUTE", 0, 0, 0, ""},
706
{ "SQL_TSI_HOUR", 0, 0, 0, ""},
707
{ "SQL_TSI_DAY", 0, 0, 0, ""},
708
{ "SQL_TSI_WEEK", 0, 0, 0, ""},
709
{ "SQL_TSI_MONTH", 0, 0, 0, ""},
710
{ "SQL_TSI_QUARTER", 0, 0, 0, ""},
711
{ "SQL_TSI_YEAR", 0, 0, 0, ""},
712
{ "SSL", 0, 0, 0, ""},
713
{ "START", 0, 0, 0, ""},
714
{ "STARTING", 0, 0, 0, ""},
715
{ "STATUS", 0, 0, 0, ""},
716
{ "STOP", 0, 0, 0, ""},
717
{ "STORAGE", 0, 0, 0, ""},
718
{ "STRAIGHT_JOIN", 0, 0, 0, ""},
719
{ "STRING", 0, 0, 0, ""},
720
{ "STRIPED", 0, 0, 0, ""},
721
{ "SUBJECT", 0, 0, 0, ""},
722
{ "SUPER", 0, 0, 0, ""},
723
{ "SUSPEND", 0, 0, 0, ""},
724
{ "TABLE", 0, 0, 0, ""},
725
{ "TABLES", 0, 0, 0, ""},
726
{ "TABLESPACE", 0, 0, 0, ""},
727
{ "TEMPORARY", 0, 0, 0, ""},
728
{ "TEMPTABLE", 0, 0, 0, ""},
729
{ "TERMINATED", 0, 0, 0, ""},
730
{ "TEXT", 0, 0, 0, ""},
731
{ "THEN", 0, 0, 0, ""},
732
{ "TIMESTAMP", 0, 0, 0, ""},
733
{ "TIMESTAMPADD", 0, 0, 0, ""},
734
{ "TIMESTAMPDIFF", 0, 0, 0, ""},
735
{ "TINYTEXT", 0, 0, 0, ""},
736
{ "TO", 0, 0, 0, ""},
737
{ "TRAILING", 0, 0, 0, ""},
738
{ "TRANSACTION", 0, 0, 0, ""},
739
{ "TRIGGER", 0, 0, 0, ""},
740
{ "TRIGGERS", 0, 0, 0, ""},
741
{ "TRUE", 0, 0, 0, ""},
742
{ "TRUNCATE", 0, 0, 0, ""},
743
{ "TYPE", 0, 0, 0, ""},
744
{ "TYPES", 0, 0, 0, ""},
745
{ "UNCOMMITTED", 0, 0, 0, ""},
746
{ "UNDEFINED", 0, 0, 0, ""},
747
{ "UNDO", 0, 0, 0, ""},
748
{ "UNICODE", 0, 0, 0, ""},
749
{ "UNION", 0, 0, 0, ""},
750
{ "UNIQUE", 0, 0, 0, ""},
751
{ "UNKNOWN", 0, 0, 0, ""},
752
{ "UNLOCK", 0, 0, 0, ""},
753
{ "UNSIGNED", 0, 0, 0, ""},
754
{ "UNTIL", 0, 0, 0, ""},
755
{ "UPDATE", 0, 0, 0, ""},
756
{ "UPGRADE", 0, 0, 0, ""},
757
{ "USAGE", 0, 0, 0, ""},
758
{ "USE", 0, 0, 0, ""},
759
{ "USER", 0, 0, 0, ""},
760
{ "USER_RESOURCES", 0, 0, 0, ""},
761
{ "USE_FRM", 0, 0, 0, ""},
762
{ "USING", 0, 0, 0, ""},
763
{ "UTC_DATE", 0, 0, 0, ""},
764
{ "UTC_TIMESTAMP", 0, 0, 0, ""},
765
{ "VALUE", 0, 0, 0, ""},
766
{ "VALUES", 0, 0, 0, ""},
767
{ "VARBINARY", 0, 0, 0, ""},
768
{ "VARCHAR", 0, 0, 0, ""},
769
{ "VARCHARACTER", 0, 0, 0, ""},
770
{ "VARIABLES", 0, 0, 0, ""},
771
{ "VARYING", 0, 0, 0, ""},
772
{ "WARNINGS", 0, 0, 0, ""},
773
{ "WEEK", 0, 0, 0, ""},
774
{ "WHEN", 0, 0, 0, ""},
775
{ "WHERE", 0, 0, 0, ""},
776
{ "WHILE", 0, 0, 0, ""},
777
{ "VIEW", 0, 0, 0, ""},
778
{ "WITH", 0, 0, 0, ""},
779
{ "WORK", 0, 0, 0, ""},
780
{ "WRITE", 0, 0, 0, ""},
781
{ "X509", 0, 0, 0, ""},
782
{ "XOR", 0, 0, 0, ""},
783
{ "XA", 0, 0, 0, ""},
784
{ "YEAR", 0, 0, 0, ""},
785
{ "YEAR_MONTH", 0, 0, 0, ""},
786
{ "ZEROFILL", 0, 0, 0, ""},
787
{ "ABS", 0, 0, 0, ""},
788
{ "ACOS", 0, 0, 0, ""},
789
{ "ADDDATE", 0, 0, 0, ""},
790
{ "AES_ENCRYPT", 0, 0, 0, ""},
791
{ "AES_DECRYPT", 0, 0, 0, ""},
792
{ "AREA", 0, 0, 0, ""},
793
{ "ASIN", 0, 0, 0, ""},
794
{ "ASBINARY", 0, 0, 0, ""},
795
{ "ASTEXT", 0, 0, 0, ""},
796
{ "ASWKB", 0, 0, 0, ""},
797
{ "ASWKT", 0, 0, 0, ""},
798
{ "ATAN", 0, 0, 0, ""},
799
{ "ATAN2", 0, 0, 0, ""},
800
{ "BENCHMARK", 0, 0, 0, ""},
801
{ "BIN", 0, 0, 0, ""},
802
{ "BIT_OR", 0, 0, 0, ""},
803
{ "BIT_AND", 0, 0, 0, ""},
804
{ "BIT_XOR", 0, 0, 0, ""},
805
{ "CAST", 0, 0, 0, ""},
806
{ "CEIL", 0, 0, 0, ""},
807
{ "CEILING", 0, 0, 0, ""},
808
{ "CENTROID", 0, 0, 0, ""},
809
{ "CHAR_LENGTH", 0, 0, 0, ""},
810
{ "CHARACTER_LENGTH", 0, 0, 0, ""},
811
{ "COALESCE", 0, 0, 0, ""},
812
{ "COERCIBILITY", 0, 0, 0, ""},
813
{ "COMPRESS", 0, 0, 0, ""},
814
{ "CONCAT", 0, 0, 0, ""},
815
{ "CONCAT_WS", 0, 0, 0, ""},
816
{ "CONNECTION_ID", 0, 0, 0, ""},
817
{ "CONV", 0, 0, 0, ""},
818
{ "CONVERT_TZ", 0, 0, 0, ""},
819
{ "COUNT", 0, 0, 0, ""},
820
{ "COS", 0, 0, 0, ""},
821
{ "COT", 0, 0, 0, ""},
822
{ "CRC32", 0, 0, 0, ""},
823
{ "CROSSES", 0, 0, 0, ""},
824
{ "CURDATE", 0, 0, 0, ""},
825
{ "DATE_ADD", 0, 0, 0, ""},
826
{ "DATEDIFF", 0, 0, 0, ""},
827
{ "DATE_FORMAT", 0, 0, 0, ""},
828
{ "DATE_SUB", 0, 0, 0, ""},
829
{ "DAYNAME", 0, 0, 0, ""},
830
{ "DAYOFMONTH", 0, 0, 0, ""},
831
{ "DAYOFWEEK", 0, 0, 0, ""},
832
{ "DAYOFYEAR", 0, 0, 0, ""},
833
{ "DECODE", 0, 0, 0, ""},
834
{ "DEGREES", 0, 0, 0, ""},
835
{ "DES_ENCRYPT", 0, 0, 0, ""},
836
{ "DES_DECRYPT", 0, 0, 0, ""},
837
{ "DIMENSION", 0, 0, 0, ""},
838
{ "DISJOINT", 0, 0, 0, ""},
839
{ "ELT", 0, 0, 0, ""},
840
{ "ENCODE", 0, 0, 0, ""},
841
{ "ENCRYPT", 0, 0, 0, ""},
842
{ "ENDPOINT", 0, 0, 0, ""},
843
{ "ENVELOPE", 0, 0, 0, ""},
844
{ "EQUALS", 0, 0, 0, ""},
845
{ "EXTERIORRING", 0, 0, 0, ""},
846
{ "EXTRACT", 0, 0, 0, ""},
847
{ "EXP", 0, 0, 0, ""},
848
{ "EXPORT_SET", 0, 0, 0, ""},
849
{ "FIELD", 0, 0, 0, ""},
850
{ "FIND_IN_SET", 0, 0, 0, ""},
851
{ "FLOOR", 0, 0, 0, ""},
852
{ "FORMAT", 0, 0, 0, ""},
853
{ "FOUND_ROWS", 0, 0, 0, ""},
854
{ "FROM_DAYS", 0, 0, 0, ""},
855
{ "FROM_UNIXTIME", 0, 0, 0, ""},
856
{ "GET_LOCK", 0, 0, 0, ""},
857
{ "GLENGTH", 0, 0, 0, ""},
858
{ "GREATEST", 0, 0, 0, ""},
859
{ "GROUP_CONCAT", 0, 0, 0, ""},
860
{ "GROUP_UNIQUE_USERS", 0, 0, 0, ""},
861
{ "HEX", 0, 0, 0, ""},
862
{ "IFNULL", 0, 0, 0, ""},
863
{ "INET_ATON", 0, 0, 0, ""},
864
{ "INET_NTOA", 0, 0, 0, ""},
865
{ "INSTR", 0, 0, 0, ""},
866
{ "INTERIORRINGN", 0, 0, 0, ""},
867
{ "INTERSECTS", 0, 0, 0, ""},
868
{ "ISCLOSED", 0, 0, 0, ""},
869
{ "ISEMPTY", 0, 0, 0, ""},
870
{ "ISNULL", 0, 0, 0, ""},
871
{ "IS_FREE_LOCK", 0, 0, 0, ""},
872
{ "IS_USED_LOCK", 0, 0, 0, ""},
873
{ "LAST_INSERT_ID", 0, 0, 0, ""},
874
{ "ISSIMPLE", 0, 0, 0, ""},
875
{ "LAST_DAY", 0, 0, 0, ""},
876
{ "LCASE", 0, 0, 0, ""},
877
{ "LEAST", 0, 0, 0, ""},
878
{ "LENGTH", 0, 0, 0, ""},
879
{ "LN", 0, 0, 0, ""},
880
{ "LINEFROMTEXT", 0, 0, 0, ""},
881
{ "LINEFROMWKB", 0, 0, 0, ""},
882
{ "LINESTRINGFROMTEXT", 0, 0, 0, ""},
883
{ "LINESTRINGFROMWKB", 0, 0, 0, ""},
884
{ "LOAD_FILE", 0, 0, 0, ""},
885
{ "LOCATE", 0, 0, 0, ""},
886
{ "LOG", 0, 0, 0, ""},
887
{ "LOG2", 0, 0, 0, ""},
888
{ "LOG10", 0, 0, 0, ""},
889
{ "LOWER", 0, 0, 0, ""},
890
{ "LPAD", 0, 0, 0, ""},
891
{ "LTRIM", 0, 0, 0, ""},
892
{ "MAKE_SET", 0, 0, 0, ""},
893
{ "MAKEDATE", 0, 0, 0, ""},
894
{ "MASTER_POS_WAIT", 0, 0, 0, ""},
895
{ "MAX", 0, 0, 0, ""},
896
{ "MBRCONTAINS", 0, 0, 0, ""},
897
{ "MBRDISJOINT", 0, 0, 0, ""},
898
{ "MBREQUAL", 0, 0, 0, ""},
899
{ "MBRINTERSECTS", 0, 0, 0, ""},
900
{ "MBROVERLAPS", 0, 0, 0, ""},
901
{ "MBRTOUCHES", 0, 0, 0, ""},
902
{ "MBRWITHIN", 0, 0, 0, ""},
903
{ "MD5", 0, 0, 0, ""},
904
{ "MID", 0, 0, 0, ""},
905
{ "MIN", 0, 0, 0, ""},
906
{ "MLINEFROMTEXT", 0, 0, 0, ""},
907
{ "MLINEFROMWKB", 0, 0, 0, ""},
908
{ "MPOINTFROMTEXT", 0, 0, 0, ""},
909
{ "MPOINTFROMWKB", 0, 0, 0, ""},
910
{ "MPOLYFROMTEXT", 0, 0, 0, ""},
911
{ "MPOLYFROMWKB", 0, 0, 0, ""},
912
{ "MONTHNAME", 0, 0, 0, ""},
913
{ "MULTILINESTRINGFROMTEXT", 0, 0, 0, ""},
914
{ "MULTILINESTRINGFROMWKB", 0, 0, 0, ""},
915
{ "MULTIPOINTFROMTEXT", 0, 0, 0, ""},
916
{ "MULTIPOINTFROMWKB", 0, 0, 0, ""},
917
{ "MULTIPOLYGONFROMTEXT", 0, 0, 0, ""},
918
{ "MULTIPOLYGONFROMWKB", 0, 0, 0, ""},
919
{ "NAME_CONST", 0, 0, 0, ""},
920
{ "NOW", 0, 0, 0, ""},
921
{ "NULLIF", 0, 0, 0, ""},
922
{ "NUMINTERIORRINGS", 0, 0, 0, ""},
923
{ "NUMPOINTS", 0, 0, 0, ""},
924
{ "OCTET_LENGTH", 0, 0, 0, ""},
925
{ "OCT", 0, 0, 0, ""},
926
{ "ORD", 0, 0, 0, ""},
927
{ "OVERLAPS", 0, 0, 0, ""},
928
{ "PERIOD_ADD", 0, 0, 0, ""},
929
{ "PERIOD_DIFF", 0, 0, 0, ""},
930
{ "PI", 0, 0, 0, ""},
931
{ "POINTFROMTEXT", 0, 0, 0, ""},
932
{ "POINTFROMWKB", 0, 0, 0, ""},
933
{ "POINTN", 0, 0, 0, ""},
934
{ "POLYFROMTEXT", 0, 0, 0, ""},
935
{ "POLYFROMWKB", 0, 0, 0, ""},
936
{ "POLYGONFROMTEXT", 0, 0, 0, ""},
937
{ "POLYGONFROMWKB", 0, 0, 0, ""},
938
{ "POSITION", 0, 0, 0, ""},
939
{ "POW", 0, 0, 0, ""},
940
{ "POWER", 0, 0, 0, ""},
941
{ "QUOTE", 0, 0, 0, ""},
942
{ "RADIANS", 0, 0, 0, ""},
943
{ "RAND", 0, 0, 0, ""},
944
{ "RELEASE_LOCK", 0, 0, 0, ""},
945
{ "REVERSE", 0, 0, 0, ""},
946
{ "ROUND", 0, 0, 0, ""},
947
{ "ROW_COUNT", 0, 0, 0, ""},
948
{ "RPAD", 0, 0, 0, ""},
949
{ "RTRIM", 0, 0, 0, ""},
950
{ "SESSION_USER", 0, 0, 0, ""},
951
{ "SUBDATE", 0, 0, 0, ""},
952
{ "SIGN", 0, 0, 0, ""},
953
{ "SIN", 0, 0, 0, ""},
954
{ "SHA", 0, 0, 0, ""},
955
{ "SHA1", 0, 0, 0, ""},
956
{ "SLEEP", 0, 0, 0, ""},
957
{ "SOUNDEX", 0, 0, 0, ""},
958
{ "SPACE", 0, 0, 0, ""},
959
{ "SQRT", 0, 0, 0, ""},
960
{ "SRID", 0, 0, 0, ""},
961
{ "STARTPOINT", 0, 0, 0, ""},
962
{ "STD", 0, 0, 0, ""},
963
{ "STDDEV", 0, 0, 0, ""},
964
{ "STDDEV_POP", 0, 0, 0, ""},
965
{ "STDDEV_SAMP", 0, 0, 0, ""},
966
{ "STR_TO_DATE", 0, 0, 0, ""},
967
{ "STRCMP", 0, 0, 0, ""},
968
{ "SUBSTR", 0, 0, 0, ""},
969
{ "SUBSTRING", 0, 0, 0, ""},
970
{ "SUBSTRING_INDEX", 0, 0, 0, ""},
971
{ "SUM", 0, 0, 0, ""},
972
{ "SYSDATE", 0, 0, 0, ""},
973
{ "SYSTEM_USER", 0, 0, 0, ""},
974
{ "TAN", 0, 0, 0, ""},
975
{ "TIME_FORMAT", 0, 0, 0, ""},
976
{ "TO_DAYS", 0, 0, 0, ""},
977
{ "TOUCHES", 0, 0, 0, ""},
978
{ "TRIM", 0, 0, 0, ""},
979
{ "UCASE", 0, 0, 0, ""},
980
{ "UNCOMPRESS", 0, 0, 0, ""},
981
{ "UNCOMPRESSED_LENGTH", 0, 0, 0, ""},
982
{ "UNHEX", 0, 0, 0, ""},
983
{ "UNIQUE_USERS", 0, 0, 0, ""},
984
{ "UNIX_TIMESTAMP", 0, 0, 0, ""},
985
{ "UPPER", 0, 0, 0, ""},
986
{ "UUID", 0, 0, 0, ""},
987
{ "VARIANCE", 0, 0, 0, ""},
988
{ "VAR_POP", 0, 0, 0, ""},
989
{ "VAR_SAMP", 0, 0, 0, ""},
990
{ "VERSION", 0, 0, 0, ""},
991
{ "WEEKDAY", 0, 0, 0, ""},
992
{ "WEEKOFYEAR", 0, 0, 0, ""},
993
{ "WITHIN", 0, 0, 0, ""},
996
{ "YEARWEEK", 0, 0, 0, ""},
998
{ (char *)NULL, 0, 0, 0, ""}
1001
static const char *load_default_groups[]= { "drizzle","client",0 };
1004
static int not_in_history(const char *line);
1005
static void initialize_readline (char *name);
1006
static void fix_history(string *final_command);
1008
static COMMANDS *find_command(const char *name,char cmd_name);
1009
static bool add_line(string *buffer,char *line,char *in_string,
1011
static void remove_cntrl(string *buffer);
1012
static void print_table_data(drizzle_result_st *result);
1013
static void print_tab_data(drizzle_result_st *result);
1014
static void print_table_data_vertically(drizzle_result_st *result);
1015
static void print_warnings(uint32_t error_code);
1016
static uint32_t start_timer(void);
1017
static void end_timer(uint32_t start_time,char *buff);
1018
static void drizzle_end_timer(uint32_t start_time,char *buff);
1019
static void nice_time(double sec,char *buff,bool part_second);
1020
extern "C" void drizzle_end(int sig);
1021
extern "C" void handle_sigint(int sig);
1022
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1023
static void window_resize(int sig);
1027
Shutdown the server that we are currently connected to.
1034
static bool server_shutdown(void)
1036
drizzle_result_st result;
1037
drizzle_return_t ret;
1041
printf("shutting down drizzled");
1042
if (opt_drizzle_port > 0)
1043
printf(" on port %d", opt_drizzle_port);
1047
if (drizzle_shutdown(&con, &result, DRIZZLE_SHUTDOWN_DEFAULT,
1048
&ret) == NULL || ret != DRIZZLE_RETURN_OK)
1050
if (ret == DRIZZLE_RETURN_ERROR_CODE)
1052
fprintf(stderr, "shutdown failed; error: '%s'",
1053
drizzle_result_error(&result));
1054
drizzle_result_free(&result);
1058
fprintf(stderr, "shutdown failed; error: '%s'",
1059
drizzle_con_error(&con));
1064
drizzle_result_free(&result);
1073
Ping the server that we are currently connected to.
1080
static bool server_ping(void)
1082
drizzle_result_st result;
1083
drizzle_return_t ret;
1085
if (drizzle_ping(&con, &result, &ret) != NULL && ret == DRIZZLE_RETURN_OK)
1088
printf("drizzled is alive\n");
1092
if (ret == DRIZZLE_RETURN_ERROR_CODE)
1094
fprintf(stderr, "ping failed; error: '%s'",
1095
drizzle_result_error(&result));
1096
drizzle_result_free(&result);
1100
fprintf(stderr, "drizzled won't answer to ping, error: '%s'",
1101
drizzle_con_error(&con));
1105
drizzle_result_free(&result);
1110
Execute command(s) specified by the user.
1112
@param error error status of command execution.
1113
If an error had occurred, this variable will be set
1114
to 1 whereas on success, it shall be set to 0. This
1115
value will be supplied to the exit() function used
1119
false no commands were executed
1121
true at least one command was executed
1123
static bool execute_commands(int *error)
1125
bool executed= false;
1130
if (server_ping() == false)
1137
if (server_shutdown() == false)
1144
int main(int argc,char *argv[])
1146
#if defined(ENABLE_NLS)
1147
# if defined(HAVE_LOCALE_H)
1148
setlocale(LC_ALL, "");
1150
bindtextdomain("drizzle", LOCALEDIR);
1151
textdomain("drizzle");
1155
delimiter_str= delimiter;
1156
default_prompt= strdup(getenv("DRIZZLE_PS1") ?
1157
getenv("DRIZZLE_PS1") :
1160
if (default_prompt == NULL)
1162
fprintf(stderr, _("Memory allocation error while constructing initial "
1163
"prompt. Aborting.\n"));
1166
current_prompt= strdup(default_prompt);
1167
if (current_prompt == NULL)
1169
fprintf(stderr, _("Memory allocation error while constructing initial "
1170
"prompt. Aborting.\n"));
1173
processed_prompt= new string();
1174
processed_prompt->reserve(32);
1178
outfile[0]=0; // no (default) outfile
1179
strcpy(pager, "stdout"); // the default, if --pager wasn't given
1181
char *tmp=getenv("PAGER");
1182
if (tmp && strlen(tmp))
1184
default_pager_set= 1;
1185
strcpy(default_pager, tmp);
1188
if (!isatty(0) || !isatty(1))
1190
status.batch=1; opt_silent=1;
1194
status.add_to_history=1;
1195
status.exit_status=1;
1199
The file descriptor-layer may be out-of-sync with the file-number layer,
1200
so we make sure that "stdout" is really open. If its file is closed then
1201
explicitly close the FD layer.
1203
int stdout_fileno_copy;
1204
stdout_fileno_copy= dup(fileno(stdout)); /* Okay if fileno fails. */
1205
if (stdout_fileno_copy == -1)
1208
close(stdout_fileno_copy); /* Clean up dup(). */
1211
internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
1213
if (get_options(argc, (char **) argv))
1215
internal::free_defaults(defaults_argv);
1220
memset(&drizzle, 0, sizeof(drizzle));
1221
if (sql_connect(current_host,current_db,current_user,opt_password,
1224
quick= 1; // Avoid history
1225
status.exit_status= 1;
1230
if (execute_commands(&command_error) != false)
1232
/* we've executed a command so exit before we go into readline mode */
1233
internal::free_defaults(defaults_argv);
1235
exit(command_error);
1238
if (status.batch && !status.line_buff)
1240
status.line_buff= new(std::nothrow) LineBuffer(opt_max_input_line, stdin);
1241
if (status.line_buff == NULL)
1243
internal::free_defaults(defaults_argv);
1250
ignore_errors=1; // Don't abort monitor
1252
if (opt_sigint_ignore)
1253
signal(SIGINT, SIG_IGN);
1255
signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
1256
signal(SIGQUIT, drizzle_end); // Catch SIGQUIT to clean up
1258
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1259
/* Readline will call this if it installs a handler */
1260
signal(SIGWINCH, window_resize);
1261
/* call the SIGWINCH handler to get the default term width */
1265
put_info(_("Welcome to the Drizzle client.. Commands end with ; or \\g."),
1268
glob_buffer= new string();
1269
glob_buffer->reserve(512);
1271
char * output_buff= (char *)malloc(512);
1272
memset(output_buff, '\0', 512);
1274
sprintf(output_buff,
1275
_("Your Drizzle connection id is %u\nServer version: %s\n"),
1276
drizzle_con_thread_id(&con),
1277
server_version_string(&con));
1278
put_info(output_buff, INFO_INFO, 0, 0);
1280
initialize_readline(current_prompt);
1281
if (!status.batch && !quick)
1283
/* read-history from file, default ~/.drizzle_history*/
1284
if (getenv("DRIZZLE_HISTFILE"))
1285
histfile= strdup(getenv("DRIZZLE_HISTFILE"));
1286
else if (getenv("HOME"))
1288
histfile=(char*) malloc(strlen(getenv("HOME")) + strlen("/.drizzle_history") + 2);
1290
sprintf(histfile,"%s/.drizzle_history",getenv("HOME"));
1291
char link_name[FN_REFLEN];
1292
ssize_t sym_link_size= readlink(histfile,link_name,FN_REFLEN-1);
1293
if (sym_link_size >= 0)
1295
link_name[sym_link_size]= '\0';
1296
if (strncmp(link_name, "/dev/null", 10) == 0)
1298
/* The .drizzle_history file is a symlink to /dev/null, don't use it */
1307
tee_fprintf(stdout, _("Reading history-file %s\n"),histfile);
1308
read_history(histfile);
1309
if (!(histfile_tmp= (char*) malloc((uint32_t) strlen(histfile) + 5)))
1311
fprintf(stderr, _("Couldn't allocate memory for temp histfile!\n"));
1314
sprintf(histfile_tmp, "%s.TMP", histfile);
1318
put_info(_("Type 'help;' or '\\h' for help. "
1319
"Type '\\c' to clear the buffer.\n"),INFO_INFO,0,0);
1320
status.exit_status= read_and_execute(!status.batch);
1325
return(0); // Keep compiler happy
1328
void drizzle_end(int sig)
1330
drizzle_con_free(&con);
1331
drizzle_free(&drizzle);
1332
if (!status.batch && !quick && histfile)
1336
tee_fprintf(stdout, _("Writing history-file %s\n"),histfile);
1337
if (!write_history(histfile_tmp))
1338
internal::my_rename(histfile_tmp, histfile, MYF(MY_WME));
1340
delete status.line_buff;
1341
status.line_buff= 0;
1344
put_info(sig ? _("Aborted") : _("Bye"), INFO_RESULT,0,0);
1347
if (processed_prompt)
1348
delete processed_prompt;
1355
free(full_username);
1356
free(part_username);
1357
free(default_prompt);
1358
free(current_prompt);
1359
internal::free_defaults(defaults_argv);
1361
exit(status.exit_status);
1366
This function handles sigint calls
1367
If query is in process, kill query
1368
no query in process, terminate like previous behavior
1371
void handle_sigint(int sig)
1373
char kill_buffer[40];
1374
drizzle_con_st kill_drizzle;
1375
drizzle_result_st res;
1376
drizzle_return_t ret;
1378
/* terminate if no query being executed, or we already tried interrupting */
1379
if (!executing_query || interrupted_query) {
1383
if (drizzle_con_add_tcp(&drizzle, &kill_drizzle, current_host,
1384
opt_drizzle_port, current_user, opt_password, NULL,
1385
opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE) == NULL)
1390
/* kill_buffer is always big enough because max length of %lu is 15 */
1391
sprintf(kill_buffer, "KILL /*!50000 QUERY */ %u",
1392
drizzle_con_thread_id(&con));
1394
if (drizzle_query_str(&kill_drizzle, &res, kill_buffer, &ret) != NULL)
1395
drizzle_result_free(&res);
1397
drizzle_con_free(&kill_drizzle);
1398
tee_fprintf(stdout, _("Query aborted by Ctrl+C\n"));
1400
interrupted_query= 1;
1409
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1410
void window_resize(int)
1412
struct winsize window_size;
1414
if (ioctl(fileno(stdin), TIOCGWINSZ, &window_size) == 0)
1415
terminal_width= window_size.ws_col;
1419
static struct my_option my_long_options[] =
1421
{"help", '?', N_("Display this help and exit."), 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1423
{"help", 'I', N_("Synonym for -?"), 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1425
{"auto-rehash", OPT_AUTO_REHASH,
1426
N_("Enable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time. Disable with --disable-auto-rehash."),
1427
(char**) &opt_rehash, (char**) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
1429
{"no-auto-rehash", 'A',
1430
N_("No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of drizzle_st and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead."),
1431
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1432
{"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
1433
N_("Automatically switch to vertical output mode if the result is wider than the terminal width."),
1434
(char**) &auto_vertical_output, (char**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1436
N_("Don't use history file. Disable interactive behavior. (Enables --silent)"), 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1437
{"column-type-info", OPT_COLUMN_TYPES, N_("Display column type information."),
1438
(char**) &column_types_flag, (char**) &column_types_flag,
1439
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1440
{"comments", 'c', N_("Preserve comments. Send comments to the server. The default is --skip-comments (discard comments), enable with --comments"),
1441
(char**) &preserve_comments, (char**) &preserve_comments,
1442
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1443
{"compress", 'C', N_("Use compression in server/client protocol."),
1444
(char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1446
{"database", 'D', N_("Database to use."), (char**) ¤t_db,
1447
(char**) ¤t_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1448
{"default-character-set", OPT_DEFAULT_CHARSET,
1449
N_("(not used)"), 0,
1450
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1451
{"delimiter", OPT_DELIMITER, N_("Delimiter to be used."), (char**) &delimiter_str,
1452
(char**) &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1453
{"execute", 'e', N_("Execute command and quit. (Disables --force and history file)"), 0,
1454
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1455
{"vertical", 'E', N_("Print the output of a query (rows) vertically."),
1456
(char**) &vertical, (char**) &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1458
{"force", 'f', N_("Continue even if we get an sql error."),
1459
(char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
1461
{"named-commands", 'G',
1462
N_("Enable named commands. Named commands mean this program's internal commands; see drizzle> help . When enabled, the named commands can be used from any line of the query, otherwise only from the first line, before an enter. Disable with --disable-named-commands. This option is disabled by default."),
1463
(char**) &named_cmds, (char**) &named_cmds, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1465
{"no-named-commands", 'g',
1466
N_("Named commands are disabled. Use \\* form only, or use named commands only in the beginning of a line ending with a semicolon (;) Since version 10.9 the client now starts with this option ENABLED by default! Disable with '-G'. Long format commands still work from the first line. WARNING: option deprecated; use --disable-named-commands instead."),
1467
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1468
{"ignore-spaces", 'i', N_("Ignore space after function names."), 0, 0, 0,
1469
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1470
{"local-infile", OPT_LOCAL_INFILE, N_("Enable/disable LOAD DATA LOCAL INFILE."),
1471
(char**) &opt_local_infile,
1472
(char**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
1473
{"no-beep", 'b', N_("Turn off beep on error."), (char**) &opt_nobeep,
1474
(char**) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1475
{"host", 'h', N_("Connect to host."), (char**) ¤t_host,
1476
(char**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1477
{"line-numbers", OPT_LINE_NUMBERS, N_("Write line numbers for errors."),
1478
(char**) &line_numbers, (char**) &line_numbers, 0, GET_BOOL,
1479
NO_ARG, 1, 0, 0, 0, 0, 0},
1480
{"skip-line-numbers", 'L', N_("Don't write line number for errors. WARNING: -L is deprecated, use long version of this option instead."), 0, 0, 0, GET_NO_ARG,
1481
NO_ARG, 0, 0, 0, 0, 0, 0},
1482
{"unbuffered", 'n', N_("Flush buffer after each query."), (char**) &unbuffered,
1483
(char**) &unbuffered, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1484
{"column-names", OPT_COLUMN_NAMES, N_("Write column names in results."),
1485
(char**) &column_names, (char**) &column_names, 0, GET_BOOL,
1486
NO_ARG, 1, 0, 0, 0, 0, 0},
1487
{"skip-column-names", 'N',
1488
N_("Don't write column names in results. WARNING: -N is deprecated, use long version of this options instead."),
1489
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1490
{"set-variable", 'O',
1491
N_("Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value."),
1492
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1493
{"sigint-ignore", OPT_SIGINT_IGNORE, N_("Ignore SIGINT (CTRL-C)"),
1494
(char**) &opt_sigint_ignore, (char**) &opt_sigint_ignore, 0, GET_BOOL,
1495
NO_ARG, 0, 0, 0, 0, 0, 0},
1496
{"one-database", 'o',
1497
N_("Only update the default database. This is useful for skipping updates to other database in the update log."),
1498
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1499
{"pager", OPT_PAGER,
1500
N_("Pager to use to display results. If you don't supply an option the default pager is taken from your ENV variable PAGER. Valid pagers are less, more, cat [> filename], etc. See interactive help (\\h) also. This option does not work in batch mode. Disable with --disable-pager. This option is disabled by default."),
1501
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1502
{"no-pager", OPT_NOPAGER,
1503
N_("Disable pager and print to stdout. See interactive help (\\h) also. WARNING: option deprecated; use --disable-pager instead."),
1504
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1506
N_("Password to use when connecting to server. If password is not given it's asked from the tty."),
1507
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1508
{"port", 'p', N_("Port number to use for connection or 0 for default to, in order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, ")
1509
N_("built-in default") " (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
1510
0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1511
{"prompt", OPT_PROMPT, N_("Set the drizzle prompt to this value."),
1512
(char**) ¤t_prompt, (char**) ¤t_prompt, 0, GET_STR_ALLOC,
1513
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1515
N_("Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file."),
1516
(char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1517
{"raw", 'r', N_("Write fields without conversion. Used with --batch."),
1518
(char**) &opt_raw_data, (char**) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1520
{"reconnect", OPT_RECONNECT, N_("Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default."),
1521
(char**) &opt_reconnect, (char**) &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
1522
{"shutdown", OPT_SHUTDOWN, N_("Shutdown the server."),
1523
(char**) &opt_shutdown, (char**) &opt_shutdown, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1524
{"silent", 's', N_("Be more silent. Print results with a tab as separator, each row on new line."), 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
1526
{"table", 't', N_("Output in table format."), (char**) &output_tables,
1527
(char**) &output_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1529
N_("Append everything into outfile. See interactive help (\\h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default."),
1530
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1531
{"no-tee", OPT_NOTEE, N_("Disable outfile. See interactive help (\\h) also. WARNING: option deprecated; use --disable-tee instead"), 0, 0, 0, GET_NO_ARG,
1532
NO_ARG, 0, 0, 0, 0, 0, 0},
1533
{"user", 'u', N_("User for login if not current user."), (char**) ¤t_user,
1534
(char**) ¤t_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1535
{"safe-updates", 'U', N_("Only allow UPDATE and DELETE that uses keys."),
1536
(char**) &safe_updates, (char**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
1538
{"i-am-a-dummy", 'U', N_("Synonym for option --safe-updates, -U."),
1539
(char**) &safe_updates, (char**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
1541
{"verbose", 'v', N_("Write more. (-v -v -v gives the table output format)."), 0,
1542
0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1543
{"version", 'V', N_("Output version information and exit."), 0, 0, 0,
1544
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1545
{"wait", 'w', N_("Wait and retry if connection is down."), 0, 0, 0, GET_NO_ARG,
1546
NO_ARG, 0, 0, 0, 0, 0, 0},
1547
{"connect_timeout", OPT_CONNECT_TIMEOUT,
1548
N_("Number of seconds before connection timeout."),
1549
(char**) &opt_connect_timeout,
1550
(char**) &opt_connect_timeout, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 3600*12, 0,
1552
{"max_input_line", OPT_MAX_INPUT_LINE,
1553
N_("Max length of input line"),
1554
(char**) &opt_max_input_line, (char**) &opt_max_input_line, 0,
1555
GET_UINT32, REQUIRED_ARG, 16 *1024L*1024L, 4096,
1556
(int64_t) 2*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
1557
{"select_limit", OPT_SELECT_LIMIT,
1558
N_("Automatic limit for SELECT when using --safe-updates"),
1559
(char**) &select_limit,
1560
(char**) &select_limit, 0, GET_UINT32, REQUIRED_ARG, 1000L, 1, ULONG_MAX,
1562
{"max_join_size", OPT_MAX_JOIN_SIZE,
1563
N_("Automatic limit for rows in a join when using --safe-updates"),
1564
(char**) &max_join_size,
1565
(char**) &max_join_size, 0, GET_UINT32, REQUIRED_ARG, 1000000L, 1, ULONG_MAX,
1567
{"secure-auth", OPT_SECURE_AUTH, N_("Refuse client connecting to server if it uses old (pre-4.1.1) protocol"), (char**) &opt_secure_auth,
1568
(char**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1569
{"show-warnings", OPT_SHOW_WARNINGS, N_("Show warnings after every statement."),
1570
(char**) &show_warnings, (char**) &show_warnings, 0, GET_BOOL, NO_ARG,
1572
{"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of lines before each import progress report."),
1573
(char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
1575
{"ping", OPT_PING, N_("Ping the server to check if it's alive."),
1576
(char**) &opt_ping, (char**) &opt_ping, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1577
{"mysql", 'm', N_("Use MySQL Protocol."),
1578
(char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
1580
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1584
static void usage(int version)
1586
const char* readline= "readline";
1588
printf(_("%s Ver %s Distrib %s, for %s-%s (%s) using %s %s\n"),
1589
internal::my_progname, VER.c_str(), drizzle_version(),
1590
HOST_VENDOR, HOST_OS, HOST_CPU,
1591
readline, rl_library_version);
1595
printf(_("Copyright (C) 2008 Sun Microsystems\n"
1596
"This software comes with ABSOLUTELY NO WARRANTY. "
1597
"This is free software,\n"
1598
"and you are welcome to modify and redistribute it "
1599
"under the GPL license\n"));
1600
printf(_("Usage: %s [OPTIONS] [database]\n"), internal::my_progname);
1601
my_print_help(my_long_options);
1602
internal::print_defaults("drizzle", load_default_groups);
1603
my_print_variables(my_long_options);
1607
static bool get_one_option(int optid, const struct my_option *, char *argument)
1609
char *endchar= NULL;
1610
uint64_t temp_drizzle_port= 0;
1613
case OPT_DEFAULT_CHARSET:
1614
default_charset_used= 1;
1617
if (argument == disabled_my_option)
1619
strcpy(delimiter, DEFAULT_DELIMITER);
1623
/* Check that delimiter does not contain a backslash */
1624
if (!strstr(argument, "\\"))
1626
strncpy(delimiter, argument, sizeof(delimiter) - 1);
1630
put_info(_("DELIMITER cannot contain a backslash character"),
1635
delimiter_length= (uint32_t)strlen(delimiter);
1636
delimiter_str= delimiter;
1639
if (argument == disabled_my_option)
1648
printf(_("WARNING: option deprecated; use --disable-tee instead.\n"));
1653
if (argument == disabled_my_option)
1658
if (argument && strlen(argument))
1660
default_pager_set= 1;
1661
strncpy(pager, argument, sizeof(pager) - 1);
1662
strcpy(default_pager, pager);
1664
else if (default_pager_set)
1665
strcpy(pager, default_pager);
1671
printf(_("WARNING: option deprecated; use --disable-pager instead.\n"));
1674
case OPT_SERVER_ARG:
1675
printf(_("WARNING: --server-arg option not supported in this configuration.\n"));
1685
status.add_to_history= 0;
1686
if (status.line_buff == NULL)
1687
status.line_buff= new(std::nothrow) LineBuffer(opt_max_input_line,NULL);
1688
if (status.line_buff == NULL)
1693
status.line_buff->addString(argument);
1696
if (argument == disabled_my_option)
1699
one_database= skip_updates= 1;
1702
temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
1703
/* if there is an alpha character this is not a valid port */
1704
if (strlen(endchar) != 0)
1706
put_info(_("Non-integer value supplied for port. If you are trying to enter a password please use --password instead."), INFO_ERROR, 0, 0);
1709
/* If the port number is > 65535 it is not a valid port
1710
This also helps with potential data loss casting unsigned long to a
1712
if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
1714
put_info(_("Value supplied for port is not valid."), INFO_ERROR, 0, 0);
1719
opt_drizzle_port= (uint32_t) temp_drizzle_port;
1723
/* Don't require password */
1724
if (argument == disabled_my_option)
1726
argument= (char*) "";
1730
char *start= argument;
1732
opt_password= strdup(argument);
1735
/* Overwriting password with 'x' */
1750
if (argument == disabled_my_option)
1756
if (argument == disabled_my_option)
1763
status.add_to_history= 0;
1764
set_if_bigger(opt_silent,1); // more silent
1778
static int get_options(int argc, char **argv)
1780
char *tmp, *pagpoint;
1783
tmp= (char *) getenv("DRIZZLE_HOST");
1785
current_host= strdup(tmp);
1787
pagpoint= getenv("PAGER");
1788
if (!((char*) (pagpoint)))
1790
strcpy(pager, "stdout");
1794
strcpy(pager, pagpoint);
1795
strcpy(default_pager, pager);
1797
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
1800
if (status.batch) /* disable pager and outfile in this case */
1802
strcpy(default_pager, "stdout");
1803
strcpy(pager, "stdout");
1805
default_pager_set= 0;
1808
connect_flag= DRIZZLE_CAPABILITIES_NONE; /* Not in interactive mode */
1820
current_db= strdup(*argv);
1823
opt_password= client_get_tty_password(NULL);
1828
static int read_and_execute(bool interactive)
1832
uint32_t line_number=0;
1835
status.exit_status=1;
1841
if (status.line_buff)
1842
line= status.line_buff->readline();
1847
if (show_progress_size > 0)
1849
if ((line_number % show_progress_size) == 0)
1850
fprintf(stderr, _("Processing line: %"PRIu32"\n"), line_number);
1852
if (!glob_buffer->empty())
1853
status.query_start_line= line_number;
1857
const char *prompt= (const char*) (ml_comment ? " /*> " :
1858
(glob_buffer->empty())
1859
? construct_prompt()
1860
: !in_string ? " -> " :
1862
" '> " : (in_string == '`' ?
1865
if (opt_outfile && glob_buffer->empty())
1869
fputs(prompt, OUTFILE);
1870
line= readline(prompt);
1872
When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS
1873
which may cause coredump.
1875
if (opt_outfile && line)
1876
fprintf(OUTFILE, "%s\n", line);
1881
status.exit_status=0;
1886
Check if line is a drizzle command line
1887
(We want to allow help, print and clear anywhere at line start
1889
if ((named_cmds || (glob_buffer->empty()))
1890
&& !ml_comment && !in_string && (com=find_command(line,0)))
1892
if ((*com->func)(glob_buffer,line) > 0)
1894
// If buffer was emptied
1895
if (glob_buffer->empty())
1897
if (interactive && status.add_to_history && not_in_history(line))
1901
if (add_line(glob_buffer,line,&in_string,&ml_comment))
1904
/* if in batch mode, send last query even if it doesn't end with \g or go */
1906
if (!interactive && !status.exit_status)
1908
remove_cntrl(glob_buffer);
1909
if (!glob_buffer->empty())
1911
status.exit_status=1;
1912
if (com_go(glob_buffer,line) <= 0)
1913
status.exit_status=0;
1917
return status.exit_status;
1921
static COMMANDS *find_command(const char *name,char cmd_char)
1933
while (my_isspace(charset_info,*name))
1936
If there is an \\g in the row or if the row has a delimiter but
1937
this is not a delimiter command, let add_line() take care of
1938
parsing the row and calling find_command()
1940
if (strstr(name, "\\g") || (strstr(name, delimiter) &&
1941
!(strlen(name) >= 9 &&
1942
!my_strnncoll(charset_info,
1943
(unsigned char*) name, 9,
1944
(const unsigned char*) "delimiter",
1946
return((COMMANDS *) 0);
1947
if ((end=strcont(name," \t")))
1949
len=(uint32_t) (end - name);
1950
while (my_isspace(charset_info,*end))
1953
end=0; // no arguments to function
1956
len=(uint32_t) strlen(name);
1959
for (uint32_t i= 0; commands[i].name; i++)
1961
if (commands[i].func &&
1962
((name && !my_strnncoll(charset_info,(const unsigned char*)name,len, (const unsigned char*)commands[i].name,len) && !commands[i].name[len] && (!end || (end && commands[i].takes_params))) || (!name && commands[i].cmd_char == cmd_char)))
1964
return(&commands[i]);
1967
return((COMMANDS *) 0);
1971
static bool add_line(string *buffer, char *line, char *in_string,
1974
unsigned char inchar;
1981
if (!line[0] && (buffer->empty()))
1983
if (status.add_to_history && line[0] && not_in_history(line))
1985
char *end_of_line=line+(uint32_t) strlen(line);
1987
for (pos=out=line ; (inchar= (unsigned char) *pos) ; pos++)
1989
if (!preserve_comments)
1991
// Skip spaces at the beggining of a statement
1992
if (my_isspace(charset_info,inchar) && (out == line) &&
1997
// Accept multi-byte characters as-is
1999
if (use_mb(charset_info) &&
2000
(length= my_ismbchar(charset_info, pos, end_of_line)))
2002
if (!*ml_comment || preserve_comments)
2012
if (!*ml_comment && inchar == '\\' &&
2013
!(*in_string && (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_NO_BACKSLASH_ESCAPES)))
2015
// Found possbile one character command like \c
2017
if (!(inchar = (unsigned char) *++pos))
2018
break; // readline adds one '\'
2019
if (*in_string || inchar == 'N') // \N is short for NULL
2020
{ // Don't allow commands in string
2022
*out++= (char) inchar;
2025
if ((com=find_command(NULL,(char) inchar)))
2027
// Flush previously accepted characters
2030
buffer->append(line, (out-line));
2034
if ((*com->func)(buffer,pos-1) > 0)
2036
if (com->takes_params)
2041
If a client-side macro appears inside a server-side comment,
2042
discard all characters in the comment after the macro (that is,
2043
until the end of the comment rather than the next delimiter)
2045
for (pos++; *pos && (*pos != '*' || *(pos + 1) != '/'); pos++)
2052
*pos && (*pos != *delimiter ||
2053
strncmp(pos + 1, delimiter + 1,
2054
strlen(delimiter + 1))) ; pos++)
2055
; // Remove parameters
2059
pos+= delimiter_length - 1; // Point at last delim char
2065
string buff(_("Unknown command: "));
2066
buff.push_back('\'');
2067
buff.push_back(inchar);
2068
buff.push_back('\'');
2069
buff.push_back('.');
2070
if (put_info(buff.c_str(),INFO_ERROR,0,0) > 0)
2073
*out++=(char) inchar;
2077
else if (!*ml_comment && !*in_string &&
2078
(end_of_line - pos) >= 10 &&
2079
!my_strnncoll(charset_info, (unsigned char*) pos, 10,
2080
(const unsigned char*) "delimiter ", 10))
2082
// Flush previously accepted characters
2085
buffer->append(line, (out - line));
2089
// Flush possible comments in the buffer
2090
if (!buffer->empty())
2092
if (com_go(buffer, 0) > 0) // < 0 is not fatal
2094
assert(buffer!=NULL);
2099
Delimiter wants the get rest of the given line as argument to
2100
allow one to change ';' to ';;' and back
2102
buffer->append(pos);
2103
if (com_delimiter(buffer, pos) > 0)
2109
else if (!*ml_comment && !*in_string && !strncmp(pos, delimiter,
2112
// Found a statement. Continue parsing after the delimiter
2113
pos+= delimiter_length;
2115
if (preserve_comments)
2117
while (my_isspace(charset_info, *pos))
2120
// Flush previously accepted characters
2123
buffer->append(line, (out-line));
2127
if (preserve_comments && ((*pos == '#') ||
2130
my_isspace(charset_info, pos[2]))))
2132
// Add trailing single line comments to this statement
2133
buffer->append(pos);
2139
if ((com= find_command(buffer->c_str(), 0)))
2142
if ((*com->func)(buffer, buffer->c_str()) > 0)
2147
if (com_go(buffer, 0) > 0) // < 0 is not fatal
2152
else if (!*ml_comment
2157
&& my_isspace(charset_info,pos[2])))))
2159
// Flush previously accepted characters
2162
buffer->append(line, (out - line));
2166
// comment to end of line
2167
if (preserve_comments)
2168
buffer->append(pos);
2172
else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
2175
if (preserve_comments)
2177
*out++= *pos++; // copy '/'
2178
*out++= *pos; // copy '*'
2185
buffer->append(line, (out-line));
2189
else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/')
2191
if (preserve_comments)
2193
*out++= *pos++; // copy '*'
2194
*out++= *pos; // copy '/'
2201
buffer->append(line, (out - line));
2204
// Consumed a 2 chars or more, and will add 1 at most,
2205
// so using the 'line' buffer to edit data in place is ok.
2210
// Add found char to buffer
2211
if (!*in_string && inchar == '/' && *(pos + 1) == '*' &&
2214
else if (!*in_string && ss_comment && inchar == '*' && *(pos + 1) == '/')
2216
if (inchar == *in_string)
2218
else if (!*ml_comment && !*in_string &&
2219
(inchar == '\'' || inchar == '"' || inchar == '`'))
2220
*in_string= (char) inchar;
2221
if (!*ml_comment || preserve_comments)
2223
if (need_space && !my_isspace(charset_info, (char)inchar))
2226
*out++= (char) inchar;
2230
if (out != line || (buffer->length() > 0))
2233
uint32_t length=(uint32_t) (out-line);
2234
if ((!*ml_comment || preserve_comments))
2235
buffer->append(line, length);
2240
/*****************************************************************
2241
Interface to Readline Completion
2242
******************************************************************/
2245
static char **mysql_completion (const char *text, int start, int end);
2246
extern "C" char *new_command_generator(const char *text, int);
2249
Tell the GNU Readline library how to complete. We want to try to complete
2250
on command names if this is the first word in the line, or on filenames
2253
static char *no_completion(const char *, int)
2255
/* No filename completion */
2260
/* glues pieces of history back together if in pieces */
2261
static void fix_history(string *final_command)
2263
int total_lines = 1;
2264
const char *ptr = final_command->c_str();
2265
char str_char = '\0'; /* Character if we are in a string or not */
2267
/* Converted buffer */
2268
string fixed_buffer;
2269
fixed_buffer.reserve(512);
2271
/* find out how many lines we have and remove newlines */
2272
while (*ptr != '\0')
2275
/* string character */
2280
if (str_char == '\0')
2282
else if (str_char == *ptr) /* close string */
2284
fixed_buffer.append(ptr, 1);
2288
not in string, change to space
2289
if in string, leave it alone
2291
fixed_buffer.append((str_char == '\0') ? " " : "\n");
2295
fixed_buffer.append("\\");
2296
/* need to see if the backslash is escaping anything */
2300
/* special characters that need escaping */
2301
if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
2302
fixed_buffer.append(ptr, 1);
2308
fixed_buffer.append(ptr, 1);
2312
if (total_lines > 1)
2313
add_history(fixed_buffer.c_str());
2317
returns 0 if line matches the previous history entry
2318
returns 1 if the line doesn't match the previous history entry
2320
static int not_in_history(const char *line)
2322
HIST_ENTRY *oldhist = history_get(history_length);
2326
if (strcmp(oldhist->line,line) == 0)
2331
static void initialize_readline (char *name)
2333
/* Allow conditional parsing of the ~/.inputrc file. */
2334
rl_readline_name= name;
2336
/* Tell the completer that we want a crack first. */
2337
rl_attempted_completion_function= (rl_completion_func_t*)&mysql_completion;
2338
rl_completion_entry_function= (drizzle_compentry_func_t*)&no_completion;
2343
Attempt to complete on the contents of TEXT. START and END show the
2344
region of TEXT that contains the word to complete. We can use the
2345
entire line in case we want to do some simple parsing. Return the
2346
array of matches, or NULL if there aren't any.
2348
char **mysql_completion (const char *text, int, int)
2350
if (!status.batch && !quick)
2351
return rl_completion_matches(text, new_command_generator);
2356
inline string lower_string(const string &from_string)
2358
string to_string= from_string;
2359
transform(to_string.begin(), to_string.end(),
2360
to_string.begin(), ::tolower);
2363
inline string lower_string(const char * from_string)
2365
string to_string= from_string;
2366
return lower_string(to_string);
2370
class CompletionMatch :
2371
public unary_function<const string&, bool>
2376
CompletionMatch(string text) : match_text(text) {}
2377
inline bool operator() (const pair<string,string> &match_against) const
2380
lower_string(match_against.first.substr(0,match_text.size()));
2381
return match_func(sub_match,match_text);
2388
char *new_command_generator(const char *text, int state)
2393
completion_string= lower_string(text);
2394
if (completion_string.size() == 0)
2396
completion_iter= completion_map.begin();
2397
completion_end= completion_map.end();
2401
completion_iter= find_if(completion_map.begin(), completion_map.end(),
2402
CompletionMatch<equal_to<string> >(completion_string));
2403
completion_end= find_if(completion_iter, completion_map.end(),
2404
CompletionMatch<not_equal_to<string> >(completion_string));
2407
if (completion_iter == completion_end || (size_t)state > completion_map.size())
2409
char *result= (char *)malloc((*completion_iter).second.size()+1);
2410
strcpy(result, (*completion_iter).second.c_str());
2415
/* Build up the completion hash */
2417
static void build_completion_hash(bool rehash, bool write_info)
2419
COMMANDS *cmd=commands;
2420
drizzle_return_t ret;
2421
drizzle_result_st databases,tables,fields;
2422
drizzle_row_t database_row,table_row;
2423
drizzle_column_st *sql_field;
2424
string tmp_str, tmp_str_lower;
2426
if (status.batch || quick || !current_db)
2427
return; // We don't need completion in batches
2431
completion_map.clear();
2433
/* hash this file's known subset of SQL commands */
2436
tmp_str_lower= lower_string(tmp_str);
2437
completion_map[tmp_str_lower]= tmp_str;
2441
/* hash Drizzle functions (to be implemented) */
2443
/* hash all database names */
2444
if (drizzle_query_str(&con, &databases, "show databases", &ret) != NULL)
2446
if (ret == DRIZZLE_RETURN_OK)
2448
if (drizzle_result_buffer(&databases) != DRIZZLE_RETURN_OK)
2449
put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
2452
while ((database_row=drizzle_row_next(&databases)))
2454
tmp_str= database_row[0];
2455
tmp_str_lower= lower_string(tmp_str);
2456
completion_map[tmp_str_lower]= tmp_str;
2461
drizzle_result_free(&databases);
2464
/* hash all table names */
2465
if (drizzle_query_str(&con, &tables, "show tables", &ret) != NULL)
2467
if (ret != DRIZZLE_RETURN_OK)
2469
drizzle_result_free(&tables);
2473
if (drizzle_result_buffer(&tables) != DRIZZLE_RETURN_OK)
2474
put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
2477
if (drizzle_result_row_count(&tables) > 0 && !opt_silent && write_info)
2479
tee_fprintf(stdout, _("\
2480
Reading table information for completion of table and column names\n \
2481
You can turn off this feature to get a quicker startup with -A\n\n"));
2483
while ((table_row=drizzle_row_next(&tables)))
2485
tmp_str= table_row[0];
2486
tmp_str_lower= lower_string(tmp_str);
2487
completion_map[tmp_str_lower]= tmp_str;
2494
/* hash all field names, both with the table prefix and without it */
2495
if (drizzle_result_row_count(&tables) == 0)
2497
drizzle_result_free(&tables);
2501
drizzle_row_seek(&tables, 0);
2503
while ((table_row=drizzle_row_next(&tables)))
2507
query.append("show fields in '");
2508
query.append(table_row[0]);
2511
if (drizzle_query(&con, &fields, query.c_str(), query.length(),
2514
if (ret == DRIZZLE_RETURN_OK &&
2515
drizzle_result_buffer(&fields) == DRIZZLE_RETURN_OK)
2517
while ((sql_field=drizzle_column_next(&fields)))
2519
tmp_str=table_row[0];
2520
tmp_str.append(".");
2521
tmp_str.append(drizzle_column_name(sql_field));
2522
tmp_str_lower= lower_string(tmp_str);
2523
completion_map[tmp_str_lower]= tmp_str;
2525
tmp_str=drizzle_column_name(sql_field);
2526
tmp_str_lower= lower_string(tmp_str);
2527
completion_map[tmp_str_lower]= tmp_str;
2530
drizzle_result_free(&fields);
2533
drizzle_result_free(&tables);
2534
completion_iter= completion_map.begin();
2537
/* for gnu readline */
2540
static int reconnect(void)
2544
put_info(_("No connection. Trying to reconnect..."),INFO_INFO,0,0);
2545
(void) com_connect((string *)0, 0);
2546
if (opt_rehash && connected)
2547
com_rehash(NULL, NULL);
2550
return put_info(_("Can't connect to the server\n"),INFO_ERROR,0,0);
2554
static void get_current_db(void)
2556
drizzle_return_t ret;
2557
drizzle_result_st res;
2561
/* In case of error below current_db will be NULL */
2562
if (drizzle_query_str(&con, &res, "SELECT DATABASE()", &ret) != NULL)
2564
if (ret == DRIZZLE_RETURN_OK &&
2565
drizzle_result_buffer(&res) == DRIZZLE_RETURN_OK)
2567
drizzle_row_t row= drizzle_row_next(&res);
2569
current_db= strdup(row[0]);
2570
drizzle_result_free(&res);
2575
/***************************************************************************
2576
The different commands
2577
***************************************************************************/
2579
int drizzleclient_real_query_for_lazy(const char *buf, int length,
2580
drizzle_result_st *result,
2581
uint32_t *error_code)
2583
drizzle_return_t ret;
2585
for (uint32_t retry=0;; retry++)
2588
if (drizzle_query(&con,result,buf,length,&ret) != NULL &&
2589
ret == DRIZZLE_RETURN_OK)
2593
error= put_error(&con, result);
2595
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2597
*error_code= drizzle_result_error_code(result);
2598
drizzle_result_free(result);
2601
if (ret != DRIZZLE_RETURN_SERVER_GONE || retry > 1 ||
2612
int drizzleclient_store_result_for_lazy(drizzle_result_st *result)
2614
if (drizzle_result_buffer(result) == DRIZZLE_RETURN_OK)
2617
if (drizzle_con_error(&con)[0])
2618
return put_error(&con, result);
2623
com_help(string *buffer, const char *)
2626
char buff[32], *end;
2628
put_info(_("List of all Drizzle commands:"), INFO_INFO,0,0);
2630
put_info(_("Note that all text commands must be first on line and end with ';'"),INFO_INFO,0,0);
2631
for (i = 0; commands[i].name; i++)
2633
end= strcpy(buff, commands[i].name);
2634
end+= strlen(commands[i].name);
2635
for (j= (int)strlen(commands[i].name); j < 10; j++)
2636
end= strcpy(end, " ")+1;
2637
if (commands[i].func)
2638
tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
2639
commands[i].cmd_char, _(commands[i].doc));
2641
tee_fprintf(stdout, "\n");
2648
com_clear(string *buffer, const char *)
2650
if (status.add_to_history)
2651
fix_history(buffer);
2660
-1 if not fatal error
2664
com_go(string *buffer, const char *)
2666
char buff[200]; /* about 110 chars used so far */
2667
char time_buff[52+3+1]; /* time max + space&parens + NUL */
2668
drizzle_result_st result;
2669
drizzle_return_t ret;
2670
uint32_t timer, warnings= 0;
2672
uint32_t error_code= 0;
2675
interrupted_query= 0;
2677
/* Remove garbage for nicer messages */
2678
remove_cntrl(buffer);
2680
if (buffer->empty())
2682
// Ignore empty quries
2685
return put_info(_("No query specified\n"),INFO_ERROR,0,0);
2688
if (!connected && reconnect())
2690
// Remove query on error
2692
return opt_reconnect ? -1 : 1; // Fatal error
2695
(void) com_print(buffer, 0);
2698
((buffer->length() < 4) || (buffer->find( "SET ") != 0)))
2700
(void) put_info(_("Ignoring query to other database"),INFO_INFO,0,0);
2704
timer=start_timer();
2706
error= drizzleclient_real_query_for_lazy(buffer->c_str(),buffer->length(),&result, &error_code);
2708
if (status.add_to_history)
2710
buffer->append(vertical ? "\\G" : delimiter);
2711
/* Append final command onto history */
2712
fix_history(buffer);
2726
if (drizzle_column_buffer(&result) != DRIZZLE_RETURN_OK)
2728
error= put_error(&con, &result);
2734
error= drizzleclient_store_result_for_lazy(&result);
2739
if (verbose >= 3 || !opt_silent)
2740
drizzle_end_timer(timer,time_buff);
2744
/* Every branch must truncate buff . */
2745
if (drizzle_result_column_count(&result) > 0)
2747
if (!quick && drizzle_result_row_count(&result) == 0 &&
2750
strcpy(buff, _("Empty set"));
2755
if (vertical || (auto_vertical_output &&
2756
(terminal_width < get_result_width(&result))))
2757
print_table_data_vertically(&result);
2758
else if (opt_silent && verbose <= 2 && !output_tables)
2759
print_tab_data(&result);
2761
print_table_data(&result);
2763
ngettext("%ld row in set","%ld rows in set",
2764
(long) drizzle_result_row_count(&result)),
2765
(long) drizzle_result_row_count(&result));
2767
if (drizzle_result_error_code(&result))
2768
error= put_error(&con, &result);
2771
else if (drizzle_result_affected_rows(&result) == ~(uint64_t) 0)
2772
strcpy(buff,_("Query OK"));
2774
sprintf(buff, ngettext("Query OK, %ld row affected",
2775
"Query OK, %ld rows affected",
2776
(long) drizzle_result_affected_rows(&result)),
2777
(long) drizzle_result_affected_rows(&result));
2779
pos= strchr(buff, '\0');
2780
if ((warnings= drizzle_result_warning_count(&result)))
2784
char warnings_buff[20];
2785
memset(warnings_buff,0,20);
2786
sprintf(warnings_buff, "%d", warnings);
2787
strcpy(pos, warnings_buff);
2788
pos+= strlen(warnings_buff);
2789
pos= strcpy(pos, " warning")+8;
2793
strcpy(pos, time_buff);
2794
put_info(buff,INFO_RESULT,0,0);
2795
if (strcmp(drizzle_result_info(&result), ""))
2796
put_info(drizzle_result_info(&result),INFO_RESULT,0,0);
2797
put_info("",INFO_RESULT,0,0); // Empty row
2801
drizzle_result_free(&result);
2803
if (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS)
2805
if (drizzle_result_read(&con, &result, &ret) == NULL ||
2806
ret != DRIZZLE_RETURN_OK)
2808
if (ret == DRIZZLE_RETURN_ERROR_CODE)
2810
error_code= drizzle_result_error_code(&result);
2811
drizzle_result_free(&result);
2814
error= put_error(&con, NULL);
2819
} while (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS);
2821
error= put_error(&con, NULL);
2825
/* Show warnings if any or error occured */
2826
if (show_warnings == 1 && (warnings >= 1 || error))
2827
print_warnings(error_code);
2829
if (!error && !status.batch &&
2830
drizzle_con_status(&con) & DRIZZLE_CON_STATUS_DB_DROPPED)
2836
return error; /* New command follows */
2840
static void init_pager()
2844
if (!(PAGER= popen(pager, "w")))
2846
tee_fprintf(stdout, "popen() failed! defaulting PAGER to stdout!\n");
2854
static void end_pager()
2861
static void init_tee(const char *file_name)
2866
if (!(new_outfile= fopen(file_name, "a")))
2868
tee_fprintf(stdout, "Error logging to file '%s'\n", file_name);
2871
OUTFILE = new_outfile;
2872
strncpy(outfile, file_name, FN_REFLEN-1);
2873
tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
2880
static void end_tee()
2890
com_ego(string *buffer,const char *line)
2893
bool oldvertical=vertical;
2895
result=com_go(buffer,line);
2896
vertical=oldvertical;
2901
static const char *fieldtype2str(drizzle_column_type_t type)
2904
case DRIZZLE_COLUMN_TYPE_BLOB: return "BLOB";
2905
case DRIZZLE_COLUMN_TYPE_DATE: return "DATE";
2906
case DRIZZLE_COLUMN_TYPE_DATETIME: return "DATETIME";
2907
case DRIZZLE_COLUMN_TYPE_NEWDECIMAL: return "DECIMAL";
2908
case DRIZZLE_COLUMN_TYPE_DOUBLE: return "DOUBLE";
2909
case DRIZZLE_COLUMN_TYPE_ENUM: return "ENUM";
2910
case DRIZZLE_COLUMN_TYPE_LONG: return "LONG";
2911
case DRIZZLE_COLUMN_TYPE_LONGLONG: return "LONGLONG";
2912
case DRIZZLE_COLUMN_TYPE_NULL: return "NULL";
2913
case DRIZZLE_COLUMN_TYPE_TIMESTAMP: return "TIMESTAMP";
2914
default: return "?-unknown-?";
2918
static char *fieldflags2str(uint32_t f) {
2919
static char buf[1024];
2922
#define ff2s_check_flag(X) \
2923
if (f & DRIZZLE_COLUMN_FLAGS_ ## X) { s=strcpy(s, # X " ")+strlen(# X " "); \
2924
f &= ~ DRIZZLE_COLUMN_FLAGS_ ## X; }
2925
ff2s_check_flag(NOT_NULL);
2926
ff2s_check_flag(PRI_KEY);
2927
ff2s_check_flag(UNIQUE_KEY);
2928
ff2s_check_flag(MULTIPLE_KEY);
2929
ff2s_check_flag(BLOB);
2930
ff2s_check_flag(UNSIGNED);
2931
ff2s_check_flag(BINARY);
2932
ff2s_check_flag(ENUM);
2933
ff2s_check_flag(AUTO_INCREMENT);
2934
ff2s_check_flag(TIMESTAMP);
2935
ff2s_check_flag(SET);
2936
ff2s_check_flag(NO_DEFAULT_VALUE);
2937
ff2s_check_flag(NUM);
2938
ff2s_check_flag(PART_KEY);
2939
ff2s_check_flag(GROUP);
2940
ff2s_check_flag(UNIQUE);
2941
ff2s_check_flag(BINCMP);
2942
ff2s_check_flag(ON_UPDATE_NOW);
2943
#undef ff2s_check_flag
2945
sprintf(s, " unknows=0x%04x", f);
2950
print_field_types(drizzle_result_st *result)
2952
drizzle_column_st *field;
2955
while ((field = drizzle_column_next(result)))
2957
tee_fprintf(PAGER, "Field %3u: `%s`\n"
2963
"Collation: %s (%u)\n"
2969
drizzle_column_name(field), drizzle_column_catalog(field),
2970
drizzle_column_db(field), drizzle_column_table(field),
2971
drizzle_column_orig_table(field),
2972
fieldtype2str(drizzle_column_type(field)),
2973
get_charset_name(drizzle_column_charset(field)),
2974
drizzle_column_charset(field), drizzle_column_size(field),
2975
drizzle_column_max_size(field), drizzle_column_decimals(field),
2976
fieldflags2str(drizzle_column_flags(field)));
2978
tee_puts("", PAGER);
2983
print_table_data(drizzle_result_st *result)
2986
drizzle_return_t ret;
2987
drizzle_column_st *field;
2991
separator.reserve(256);
2993
num_flag=(bool*) malloc(sizeof(bool)*drizzle_result_column_count(result));
2994
if (column_types_flag)
2996
print_field_types(result);
2997
if (!drizzle_result_row_count(result))
2999
drizzle_column_seek(result,0);
3001
separator.append("+");
3002
while ((field = drizzle_column_next(result)))
3004
uint32_t x, length= 0;
3008
uint32_t name_length= strlen(drizzle_column_name(field));
3010
/* Check if the max_byte value is really the maximum in terms
3011
of visual length since multibyte characters can affect the
3012
length of the separator. */
3013
length= charset_info->cset->numcells(charset_info,
3014
drizzle_column_name(field),
3015
drizzle_column_name(field) +
3018
if (name_length == drizzle_column_max_size(field))
3020
if (length < drizzle_column_max_size(field))
3021
drizzle_column_set_max_size(field, length);
3025
length= name_length;
3030
length=max(length,drizzle_column_size(field));
3032
length=max(length,(uint32_t)drizzle_column_max_size(field));
3034
!(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
3039
drizzle_column_set_max_size(field, length);
3041
for (x=0; x< (length+2); x++)
3042
separator.append("-");
3043
separator.append("+");
3046
tee_puts((char*) separator.c_str(), PAGER);
3049
drizzle_column_seek(result,0);
3050
(void) tee_fputs("|", PAGER);
3051
for (uint32_t off=0; (field = drizzle_column_next(result)) ; off++)
3053
uint32_t name_length= (uint32_t) strlen(drizzle_column_name(field));
3054
uint32_t numcells= charset_info->cset->numcells(charset_info,
3055
drizzle_column_name(field),
3056
drizzle_column_name(field) +
3058
uint32_t display_length= drizzle_column_max_size(field) + name_length -
3060
tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
3062
drizzle_column_name(field));
3063
num_flag[off]= ((drizzle_column_type(field) <= DRIZZLE_COLUMN_TYPE_LONGLONG) ||
3064
(drizzle_column_type(field) == DRIZZLE_COLUMN_TYPE_NEWDECIMAL));
3066
(void) tee_fputs("\n", PAGER);
3067
tee_puts((char*) separator.c_str(), PAGER);
3074
cur= drizzle_row_buffer(result, &ret);
3075
if (ret != DRIZZLE_RETURN_OK)
3077
(void)put_error(&con, result);
3082
cur= drizzle_row_next(result);
3084
if (cur == NULL || interrupted_query)
3087
size_t *lengths= drizzle_row_field_sizes(result);
3088
(void) tee_fputs("| ", PAGER);
3089
drizzle_column_seek(result, 0);
3090
for (uint32_t off= 0; off < drizzle_result_column_count(result); off++)
3093
uint32_t data_length;
3094
uint32_t field_max_length;
3095
uint32_t visible_length;
3096
uint32_t extra_padding;
3098
if (cur[off] == NULL)
3106
data_length= (uint32_t) lengths[off];
3109
field= drizzle_column_next(result);
3110
field_max_length= drizzle_column_max_size(field);
3113
How many text cells on the screen will this string span? If it contains
3114
multibyte characters, then the number of characters we occupy on screen
3115
will be fewer than the number of bytes we occupy in memory.
3117
We need to find how much screen real-estate we will occupy to know how
3118
many extra padding-characters we should send with the printing function.
3120
visible_length= charset_info->cset->numcells(charset_info, buffer, buffer + data_length);
3121
extra_padding= data_length - visible_length;
3123
if (field_max_length > MAX_COLUMN_LENGTH)
3124
tee_print_sized_data(buffer, data_length, MAX_COLUMN_LENGTH+extra_padding, false);
3127
if (num_flag[off] != 0) /* if it is numeric, we right-justify it */
3128
tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, true);
3130
tee_print_sized_data(buffer, data_length,
3131
field_max_length+extra_padding, false);
3133
tee_fputs(" | ", PAGER);
3135
(void) tee_fputs("\n", PAGER);
3137
drizzle_row_free(result, cur);
3139
tee_puts(separator.c_str(), PAGER);
3144
Return the length of a field after it would be rendered into text.
3146
This doesn't know or care about multibyte characters. Assume we're
3147
using such a charset. We can't know that all of the upcoming rows
3148
for this column will have bytes that each render into some fraction
3149
of a character. It's at least possible that a row has bytes that
3150
all render into one character each, and so the maximum length is
3151
still the number of bytes. (Assumption 1: This can't be better
3152
because we can never know the number of characters that the DB is
3153
going to send -- only the number of bytes. 2: Chars <= Bytes.)
3155
@param field Pointer to a field to be inspected
3157
@returns number of character positions to be used, at most
3159
static int get_field_disp_length(drizzle_column_st *field)
3161
uint32_t length= column_names ? strlen(drizzle_column_name(field)) : 0;
3164
length= max(length, drizzle_column_size(field));
3166
length= max(length, (uint32_t)drizzle_column_max_size(field));
3169
!(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
3171
length= 4; /* Room for "NULL" */
3178
For a new result, return the max number of characters that any
3179
upcoming row may return.
3181
@param result Pointer to the result to judge
3183
@returns The max number of characters in any row of this result
3185
static int get_result_width(drizzle_result_st *result)
3187
unsigned int len= 0;
3188
drizzle_column_st *field;
3191
offset= drizzle_column_current(result);
3192
assert(offset == 0);
3194
while ((field= drizzle_column_next(result)) != NULL)
3195
len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
3197
(void) drizzle_column_seek(result, offset);
3199
return len + 1; /* plus final bar. */
3203
tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified)
3206
For '\0's print ASCII spaces instead, as '\0' is eaten by (at
3207
least my) console driver, and that messes up the pretty table
3208
grid. (The \0 is also the reason we can't use fprintf() .)
3213
if (right_justified)
3214
for (i= data_length; i < total_bytes_to_send; i++)
3215
tee_putc((int)' ', PAGER);
3217
for (i= 0, p= data; i < data_length; i+= 1, p+= 1)
3220
tee_putc((int)' ', PAGER);
3222
tee_putc((int)*p, PAGER);
3225
if (! right_justified)
3226
for (i= data_length; i < total_bytes_to_send; i++)
3227
tee_putc((int)' ', PAGER);
3233
print_table_data_vertically(drizzle_result_st *result)
3236
drizzle_return_t ret;
3237
uint32_t max_length=0;
3238
drizzle_column_st *field;
3240
while ((field = drizzle_column_next(result)))
3242
uint32_t length= strlen(drizzle_column_name(field));
3243
if (length > max_length)
3245
drizzle_column_set_max_size(field, length);
3248
for (uint32_t row_count=1;; row_count++)
3252
cur= drizzle_row_buffer(result, &ret);
3253
if (ret != DRIZZLE_RETURN_OK)
3255
(void)put_error(&con, result);
3260
cur= drizzle_row_next(result);
3262
if (cur == NULL || interrupted_query)
3264
drizzle_column_seek(result,0);
3266
"*************************** %d. row ***************************\n", row_count);
3267
for (uint32_t off=0; off < drizzle_result_column_count(result); off++)
3269
field= drizzle_column_next(result);
3270
tee_fprintf(PAGER, "%*s: ",(int) max_length,drizzle_column_name(field));
3271
tee_fprintf(PAGER, "%s\n",cur[off] ? (char*) cur[off] : "NULL");
3274
drizzle_row_free(result, cur);
3279
/* print_warnings should be called right after executing a statement */
3281
static void print_warnings(uint32_t error_code)
3284
drizzle_result_st result;
3287
uint32_t new_code= 0;
3289
/* Get the warnings */
3290
query= "show warnings";
3291
drizzleclient_real_query_for_lazy(query, strlen(query),&result,&new_code);
3292
drizzleclient_store_result_for_lazy(&result);
3294
/* Bail out when no warnings */
3295
if (!(num_rows= drizzle_result_row_count(&result)))
3298
cur= drizzle_row_next(&result);
3301
Don't print a duplicate of the current error. It is possible for SHOW
3302
WARNINGS to return multiple errors with the same code, but different
3303
messages. To be safe, skip printing the duplicate only if it is the only
3306
if (!cur || (num_rows == 1 &&
3307
error_code == (uint32_t) strtoul(cur[1], NULL, 10)))
3312
/* Print the warnings */
3316
tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]);
3317
} while ((cur= drizzle_row_next(&result)));
3321
drizzle_result_free(&result);
3326
safe_put_field(const char *pos,uint32_t length)
3329
tee_fputs("NULL", PAGER);
3333
tee_fputs(pos, PAGER);
3334
else for (const char *end=pos+length ; pos != end ; pos++)
3337
if (use_mb(charset_info) &&
3338
(l = my_ismbchar(charset_info, pos, end)))
3341
tee_putc(*pos++, PAGER);
3346
tee_fputs("\\0", PAGER); // This makes everything hard
3347
else if (*pos == '\t')
3348
tee_fputs("\\t", PAGER); // This would destroy tab format
3349
else if (*pos == '\n')
3350
tee_fputs("\\n", PAGER); // This too
3351
else if (*pos == '\\')
3352
tee_fputs("\\\\", PAGER);
3354
tee_putc(*pos, PAGER);
3361
print_tab_data(drizzle_result_st *result)
3364
drizzle_return_t ret;
3365
drizzle_column_st *field;
3368
if (opt_silent < 2 && column_names)
3371
while ((field = drizzle_column_next(result)))
3374
(void) tee_fputs("\t", PAGER);
3375
(void) tee_fputs(drizzle_column_name(field), PAGER);
3377
(void) tee_fputs("\n", PAGER);
3383
cur= drizzle_row_buffer(result, &ret);
3384
if (ret != DRIZZLE_RETURN_OK)
3386
(void)put_error(&con, result);
3391
cur= drizzle_row_next(result);
3396
lengths= drizzle_row_field_sizes(result);
3397
safe_put_field(cur[0],lengths[0]);
3398
for (uint32_t off=1 ; off < drizzle_result_column_count(result); off++)
3400
(void) tee_fputs("\t", PAGER);
3401
safe_put_field(cur[off], lengths[off]);
3403
(void) tee_fputs("\n", PAGER);
3405
drizzle_row_free(result, cur);
3410
com_tee(string *, const char *line )
3412
char file_name[FN_REFLEN], *end;
3417
while (my_isspace(charset_info,*line))
3419
if (!(param = strchr(line, ' '))) // if outfile wasn't given, use the default
3421
if (!strlen(outfile))
3423
printf("No previous outfile available, you must give a filename!\n");
3426
else if (opt_outfile)
3428
tee_fprintf(stdout, "Currently logging to file '%s'\n", outfile);
3432
param = outfile; //resume using the old outfile
3435
/* eliminate the spaces before the parameters */
3436
while (my_isspace(charset_info,*param))
3438
strncpy(file_name, param, sizeof(file_name) - 1);
3439
end= file_name + strlen(file_name);
3440
/* remove end space from command line */
3441
while (end > file_name && (my_isspace(charset_info,end[-1]) ||
3442
my_iscntrl(charset_info,end[-1])))
3445
if (end == file_name)
3447
printf("No outfile specified!\n");
3450
init_tee(file_name);
3456
com_notee(string *, const char *)
3460
tee_fprintf(stdout, "Outfile disabled.\n");
3465
Sorry, this command is not available in Windows.
3469
com_pager(string *, const char *line)
3471
char pager_name[FN_REFLEN], *end;
3476
/* Skip spaces in front of the pager command */
3477
while (my_isspace(charset_info, *line))
3479
/* Skip the pager command */
3480
param= strchr(line, ' ');
3481
/* Skip the spaces between the command and the argument */
3482
while (param && my_isspace(charset_info, *param))
3484
if (!param || !strlen(param)) // if pager was not given, use the default
3486
if (!default_pager_set)
3488
tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
3490
strcpy(pager, "stdout");
3494
strcpy(pager, default_pager);
3498
end= strncpy(pager_name, param, sizeof(pager_name)-1);
3499
end+= strlen(pager_name);
3500
while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
3501
my_iscntrl(charset_info,end[-1])))
3504
strcpy(pager, pager_name);
3505
strcpy(default_pager, pager_name);
3508
tee_fprintf(stdout, "PAGER set to '%s'\n", pager);
3514
com_nopager(string *, const char *)
3516
strcpy(pager, "stdout");
3519
tee_fprintf(stdout, "PAGER set to stdout\n");
3523
/* If arg is given, exit without errors. This happens on command 'quit' */
3526
com_quit(string *, const char *)
3528
/* let the screen auto close on a normal shutdown */
3529
status.exit_status=0;
3534
com_rehash(string *, const char *)
3536
build_completion_hash(1, 0);
3543
com_print(string *buffer,const char *)
3545
tee_puts("--------------", stdout);
3546
(void) tee_fputs(buffer->c_str(), stdout);
3547
if ( (buffer->length() == 0)
3548
|| (buffer->c_str())[(buffer->length())-1] != '\n')
3549
tee_putc('\n', stdout);
3550
tee_puts("--------------\n", stdout);
3551
/* If empty buffer */
3557
com_connect(string *buffer, const char *line)
3559
char *tmp, buff[256];
3560
bool save_rehash= opt_rehash;
3563
memset(buff, 0, sizeof(buff));
3567
Two null bytes are needed in the end of buff to allow
3568
get_arg to find end of string the second time it's called.
3570
tmp= strncpy(buff, line, sizeof(buff)-2);
3574
tmp= get_arg(buff, 0);
3578
current_db= strdup(tmp);
3579
tmp= get_arg(buff, 1);
3583
current_host=strdup(tmp);
3588
/* Quick re-connect */
3592
assert(buffer!=NULL);
3597
error=sql_connect(current_host,current_db,current_user,opt_password,0);
3598
opt_rehash= save_rehash;
3602
sprintf(buff,"Connection id: %u",drizzle_con_thread_id(&con));
3603
put_info(buff,INFO_INFO,0,0);
3604
sprintf(buff,"Current database: %.128s\n",
3605
current_db ? current_db : "*** NONE ***");
3606
put_info(buff,INFO_INFO,0,0);
3612
static int com_source(string *, const char *line)
3614
char source_name[FN_REFLEN], *end;
3616
LineBuffer *line_buff;
3621
/* Skip space from file name */
3622
while (my_isspace(charset_info,*line))
3624
if (!(param = strchr(line, ' '))) // Skip command name
3625
return put_info("Usage: \\. <filename> | source <filename>",
3627
while (my_isspace(charset_info,*param))
3629
end= strncpy(source_name,param,sizeof(source_name)-1);
3630
end+= strlen(source_name);
3631
while (end > source_name && (my_isspace(charset_info,end[-1]) ||
3632
my_iscntrl(charset_info,end[-1])))
3635
internal::unpack_filename(source_name,source_name);
3636
/* open file name */
3637
if (!(sql_file = fopen(source_name, "r")))
3639
char buff[FN_REFLEN+60];
3640
sprintf(buff,"Failed to open file '%s', error: %d", source_name,errno);
3641
return put_info(buff, INFO_ERROR, 0 ,0);
3644
line_buff= new(std::nothrow) LineBuffer(opt_max_input_line,sql_file);
3645
if (line_buff == NULL)
3648
return put_info("Can't initialize LineBuffer", INFO_ERROR, 0, 0);
3651
/* Save old status */
3653
memset(&status, 0, sizeof(status));
3655
// Run in batch mode
3656
status.batch=old_status.batch;
3657
status.line_buff=line_buff;
3658
status.file_name=source_name;
3659
// Empty command buffer
3660
assert(glob_buffer!=NULL);
3661
glob_buffer->clear();
3662
error= read_and_execute(false);
3663
// Continue as before
3666
delete status.line_buff;
3667
line_buff= status.line_buff= 0;
3674
com_delimiter(string *, const char *line)
3676
char buff[256], *tmp;
3678
strncpy(buff, line, sizeof(buff) - 1);
3679
tmp= get_arg(buff, 0);
3683
put_info("DELIMITER must be followed by a 'delimiter' character or string",
3689
if (strstr(tmp, "\\"))
3691
put_info("DELIMITER cannot contain a backslash character",
3696
strncpy(delimiter, tmp, sizeof(delimiter) - 1);
3697
delimiter_length= (int)strlen(delimiter);
3698
delimiter_str= delimiter;
3704
com_use(string *, const char *line)
3706
char *tmp, buff[FN_REFLEN + 1];
3708
drizzle_result_st result;
3709
drizzle_return_t ret;
3711
memset(buff, 0, sizeof(buff));
3712
strncpy(buff, line, sizeof(buff) - 1);
3713
tmp= get_arg(buff, 0);
3716
put_info("USE must be followed by a database name", INFO_ERROR, 0, 0);
3720
We need to recheck the current database, because it may change
3721
under our feet, for example if DROP DATABASE or RENAME DATABASE
3722
(latter one not yet available by the time the comment was written)
3726
if (!current_db || strcmp(current_db,tmp))
3731
select_db= 0; // don't do drizzleclient_select_db()
3734
select_db= 2; // do drizzleclient_select_db() and build_completion_hash()
3739
USE to the current db specified.
3740
We do need to send drizzleclient_select_db() to make server
3741
update database level privileges, which might
3742
change since last USE (see bug#10979).
3743
For performance purposes, we'll skip rebuilding of completion hash.
3746
select_db= 1; // do only drizzleclient_select_db(), without completion
3752
reconnect once if connection is down or if connection was found to
3753
be down during query
3755
if (!connected && reconnect())
3756
return opt_reconnect ? -1 : 1; // Fatal error
3757
for (bool try_again= true; try_again; try_again= false)
3759
if (drizzle_select_db(&con,&result,tmp,&ret) == NULL ||
3760
ret != DRIZZLE_RETURN_OK)
3762
if (ret == DRIZZLE_RETURN_ERROR_CODE)
3764
int error= put_error(&con, &result);
3765
drizzle_result_free(&result);
3769
if (ret != DRIZZLE_RETURN_SERVER_GONE || !try_again)
3770
return put_error(&con, NULL);
3773
return opt_reconnect ? -1 : 1; // Fatal error
3776
drizzle_result_free(&result);
3779
current_db= strdup(tmp);
3781
build_completion_hash(opt_rehash, 1);
3784
put_info("Database changed",INFO_INFO, 0, 0);
3789
com_warnings(string *, const char *)
3792
put_info("Show warnings enabled.",INFO_INFO, 0, 0);
3797
com_nowarnings(string *, const char *)
3800
put_info("Show warnings disabled.",INFO_INFO, 0, 0);
3805
Gets argument from a command on the command line. If get_next_arg is
3806
not defined, skips the command and returns the first argument. The
3807
line is modified by adding zero to the end of the argument. If
3808
get_next_arg is defined, then the function searches for end of string
3809
first, after found, returns the next argument and adds zero to the
3810
end. If you ever wish to use this feature, remember to initialize all
3811
items in the array to zero first.
3814
char *get_arg(char *line, bool get_next_arg)
3817
bool quoted= 0, valid_arg= 0;
3823
for (; *ptr; ptr++) ;
3829
/* skip leading white spaces */
3830
while (my_isspace(charset_info, *ptr))
3832
if (*ptr == '\\') // short command was used
3835
while (*ptr &&!my_isspace(charset_info, *ptr)) // skip command
3840
while (my_isspace(charset_info, *ptr))
3842
if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
3848
for (start=ptr ; *ptr; ptr++)
3850
if (*ptr == '\\' && ptr[1]) // escaped character
3852
// Remove the backslash
3855
else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
3861
valid_arg= ptr != start;
3862
return valid_arg ? start : NULL;
3867
sql_connect(char *host,char *database,char *user,char *password,
3870
drizzle_return_t ret;
3875
drizzle_con_free(&con);
3876
drizzle_free(&drizzle);
3878
drizzle_create(&drizzle);
3879
if (drizzle_con_add_tcp(&drizzle, &con, host, opt_drizzle_port, user,
3880
password, database, opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE) == NULL)
3882
(void) put_error(&con, NULL);
3883
(void) fflush(stdout);
3887
/* XXX add this back in
3888
if (opt_connect_timeout)
3890
uint32_t timeout=opt_connect_timeout;
3891
drizzleclient_options(&drizzle,DRIZZLE_OPT_CONNECT_TIMEOUT,
3896
/* XXX Do we need this?
3899
char init_command[100];
3900
sprintf(init_command,
3901
"SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%"PRIu32
3902
",MAX_JOIN_SIZE=%"PRIu32,
3903
select_limit, max_join_size);
3904
drizzleclient_options(&drizzle, DRIZZLE_INIT_COMMAND, init_command);
3907
if ((ret= drizzle_con_connect(&con)) != DRIZZLE_RETURN_OK)
3909
if (!silent || (ret != DRIZZLE_RETURN_GETADDRINFO &&
3910
ret != DRIZZLE_RETURN_COULD_NOT_CONNECT))
3912
(void) put_error(&con, NULL);
3913
(void) fflush(stdout);
3914
return ignore_errors ? -1 : 1; // Abort
3916
return -1; // Retryable
3920
build_completion_hash(opt_rehash, 1);
3926
com_status(string *, const char *)
3932
drizzle_result_st result;
3933
drizzle_return_t ret;
3935
tee_puts("--------------", stdout);
3936
usage(1); /* Print version */
3939
tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",drizzle_con_thread_id(&con));
3941
Don't remove "limit 1",
3942
it is protection againts SQL_SELECT_LIMIT=0
3944
if (drizzle_query_str(&con,&result,"select DATABASE(), USER() limit 1",
3945
&ret) != NULL && ret == DRIZZLE_RETURN_OK &&
3946
drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
3948
drizzle_row_t cur=drizzle_row_next(&result);
3951
tee_fprintf(stdout, "Current database:\t%s\n", cur[0] ? cur[0] : "");
3952
tee_fprintf(stdout, "Current user:\t\t%s\n", cur[1]);
3954
drizzle_result_free(&result);
3956
else if (ret == DRIZZLE_RETURN_ERROR_CODE)
3957
drizzle_result_free(&result);
3958
tee_puts("SSL:\t\t\tNot in use", stdout);
3963
tee_fprintf(stdout, "\nNo connection\n");
3970
tee_fprintf(stdout, "\nAll updates ignored to this database\n");
3973
tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
3974
tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
3975
tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
3976
tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&con));
3977
tee_fprintf(stdout, "Protocol version:\t%d\n", drizzle_con_protocol_version(&con));
3978
tee_fprintf(stdout, "Connection:\t\t%s\n", drizzle_con_host(&con));
3979
/* XXX need to save this from result
3980
if ((id= drizzleclient_insert_id(&drizzle)))
3981
tee_fprintf(stdout, "Insert id:\t\t%s\n", internal::llstr(id, buff));
3984
if (strcmp(drizzle_con_uds(&con), ""))
3985
tee_fprintf(stdout, "UNIX socket:\t\t%s\n", drizzle_con_uds(&con));
3987
tee_fprintf(stdout, "TCP port:\t\t%d\n", drizzle_con_port(&con));
3992
tee_fprintf(stdout, "\nNote that you are running in safe_update_mode:\n");
3994
tee_fprintf(stdout, "\
3995
UPDATEs and DELETEs that don't use a key in the WHERE clause are not allowed.\n\
3996
(One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n \
3997
SELECT has an automatic 'LIMIT %lu' if LIMIT is not used.\n \
3998
Max number of examined row combination in a join is set to: %lu\n\n",
3999
select_limit, max_join_size);
4001
tee_puts("--------------\n", stdout);
4006
server_version_string(drizzle_con_st *local_con)
4008
static string buf("");
4009
static bool server_version_string_reserved= false;
4011
if (!server_version_string_reserved)
4013
buf.reserve(MAX_SERVER_VERSION_LENGTH);
4014
server_version_string_reserved= true;
4016
/* Only one thread calls this, so no synchronization is needed */
4019
drizzle_result_st result;
4020
drizzle_return_t ret;
4022
buf.append(drizzle_con_server_version(local_con));
4024
/* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
4025
(void)drizzle_query_str(local_con, &result,
4026
"select @@version_comment limit 1", &ret);
4027
if (ret == DRIZZLE_RETURN_OK &&
4028
drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
4030
drizzle_row_t cur = drizzle_row_next(&result);
4036
drizzle_result_free(&result);
4038
else if (ret == DRIZZLE_RETURN_ERROR_CODE)
4039
drizzle_result_free(&result);
4046
put_info(const char *str,INFO_TYPE info_type, uint32_t error, const char *sqlstate)
4048
FILE *file= (info_type == INFO_ERROR ? stderr : stdout);
4049
static int inited=0;
4053
if (info_type == INFO_ERROR)
4055
(void) fflush(file);
4056
fprintf(file,"ERROR");
4060
(void) fprintf(file," %d (%s)",error, sqlstate);
4062
(void) fprintf(file," %d",error);
4064
if (status.query_start_line && line_numbers)
4066
(void) fprintf(file," at line %"PRIu32,status.query_start_line);
4067
if (status.file_name)
4068
(void) fprintf(file," in file: '%s'", status.file_name);
4070
(void) fprintf(file,": %s\n",str);
4071
(void) fflush(file);
4075
else if (info_type == INFO_RESULT && verbose > 1)
4076
tee_puts(str, file);
4079
return info_type == INFO_ERROR ? -1 : 0;
4081
if (!opt_silent || info_type == INFO_ERROR)
4086
#ifdef HAVE_SETUPTERM
4087
(void) setupterm((char *)0, 1, (int *) 0);
4090
if (info_type == INFO_ERROR)
4093
/* This should make a bell */
4095
vidattr(A_STANDOUT);
4099
(void) tee_fprintf(file, "ERROR %d (%s): ", error, sqlstate);
4101
(void) tee_fprintf(file, "ERROR %d: ", error);
4104
tee_puts("ERROR: ", file);
4108
(void) tee_puts(str, file);
4113
return info_type == INFO_ERROR ? -1 : 0;
4118
put_error(drizzle_con_st *local_con, drizzle_result_st *res)
4124
error= drizzle_result_error(res);
4125
if (!strcmp(error, ""))
4126
error= drizzle_con_error(local_con);
4129
error= drizzle_con_error(local_con);
4131
return put_info(error, INFO_ERROR,
4132
res == NULL ? drizzle_con_error_code(local_con) :
4133
drizzle_result_error_code(res),
4134
res == NULL ? drizzle_con_sqlstate(local_con) :
4135
drizzle_result_sqlstate(res));
4139
static void remove_cntrl(string *buffer)
4141
const char *start= buffer->c_str();
4142
const char *end= start + (buffer->length());
4143
while (start < end && !my_isgraph(charset_info,end[-1]))
4145
uint32_t pos_to_truncate= (end-start);
4146
if (buffer->length() > pos_to_truncate)
4147
buffer->erase(pos_to_truncate);
4151
void tee_fprintf(FILE *file, const char *fmt, ...)
4155
va_start(args, fmt);
4156
(void) vfprintf(file, fmt, args);
4161
va_start(args, fmt);
4162
(void) vfprintf(OUTFILE, fmt, args);
4168
void tee_fputs(const char *s, FILE *file)
4176
void tee_puts(const char *s, FILE *file)
4183
fputc('\n', OUTFILE);
4187
void tee_putc(int c, FILE *file)
4194
#include <sys/times.h>
4195
#ifdef _SC_CLK_TCK // For mit-pthreads
4196
#undef CLOCKS_PER_SEC
4197
#define CLOCKS_PER_SEC (sysconf(_SC_CLK_TCK))
4200
static uint32_t start_timer(void)
4203
return times(&tms_tmp);
4208
Write as many as 52+1 bytes to buff, in the form of a legible
4211
len("4294967296 days, 23 hours, 59 minutes, 60.00 seconds") -> 52
4213
static void nice_time(double sec,char *buff,bool part_second)
4216
ostringstream tmp_buff_str;
4218
if (sec >= 3600.0*24)
4220
tmp=(uint32_t) floor(sec/(3600.0*24));
4221
sec-= 3600.0*24*tmp;
4222
tmp_buff_str << tmp;
4225
tmp_buff_str << " days ";
4227
tmp_buff_str << " day ";
4232
tmp=(uint32_t) floor(sec/3600.0);
4234
tmp_buff_str << tmp;
4237
tmp_buff_str << " hours ";
4239
tmp_buff_str << " hour ";
4243
tmp=(uint32_t) floor(sec/60.0);
4245
tmp_buff_str << tmp << " min ";
4248
tmp_buff_str.precision(2);
4250
tmp_buff_str.precision(0);
4251
tmp_buff_str << sec << " sec";
4252
strcpy(buff, tmp_buff_str.str().c_str());
4256
static void end_timer(uint32_t start_time,char *buff)
4258
nice_time((double) (start_timer() - start_time) /
4259
CLOCKS_PER_SEC,buff,1);
4263
static void drizzle_end_timer(uint32_t start_time,char *buff)
4267
end_timer(start_time,buff+2);
4268
strcpy(strchr(buff, '\0'),")");
4271
static const char * construct_prompt()
4273
// Erase the old prompt
4274
assert(processed_prompt!=NULL);
4275
processed_prompt->clear();
4277
// Get the date struct
4278
time_t lclock = time(NULL);
4279
struct tm *t = localtime(&lclock);
4281
/* parse thru the settings for the prompt */
4282
for (char *c= current_prompt; *c; (void)*c++)
4284
if (*c != PROMPT_CHAR)
4286
processed_prompt->append(c, 1);
4292
/* Room for Dow MMM DD HH:MM:SS YYYY */
4296
// stop it from going beyond if ends with %
4300
add_int_to_prompt(++prompt_counter);
4304
processed_prompt->append(drizzle_con_server_version(&con));
4306
processed_prompt->append("not_connected");
4309
processed_prompt->append(current_db ? current_db : "(none)");
4314
prompt= connected ? drizzle_con_host(&con) : "not_connected";
4315
if (strstr(prompt, "Localhost"))
4316
processed_prompt->append("localhost");
4319
const char *end=strrchr(prompt,' ');
4321
processed_prompt->append(prompt, (end-prompt));
4329
processed_prompt->append("not_connected");
4333
if (strcmp(drizzle_con_uds(&con), ""))
4335
const char *pos=strrchr(drizzle_con_uds(&con),'/');
4336
processed_prompt->append(pos ? pos+1 : drizzle_con_uds(&con));
4339
add_int_to_prompt(drizzle_con_port(&con));
4345
processed_prompt->append(full_username ? full_username :
4346
(current_user ? current_user : "(unknown)"));
4351
processed_prompt->append(part_username ? part_username :
4352
(current_user ? current_user : "(unknown)"));
4356
processed_prompt->append(PROMPT_CHAR, 1);
4361
processed_prompt->append('\n', 1);
4367
processed_prompt->append(' ', 1);
4371
if (t->tm_hour < 10)
4372
add_int_to_prompt(0);
4373
add_int_to_prompt(t->tm_hour);
4376
getHour = t->tm_hour % 12;
4380
add_int_to_prompt(0);
4381
add_int_to_prompt(getHour);
4385
add_int_to_prompt(0);
4386
add_int_to_prompt(t->tm_min);
4389
getYear = t->tm_year % 100;
4391
add_int_to_prompt(0);
4392
add_int_to_prompt(getYear);
4395
add_int_to_prompt(t->tm_year+1900);
4398
strftime(dateTime, 32, "%a %b %d %H:%M:%S %Y", localtime(&lclock));
4399
processed_prompt->append(dateTime);
4403
add_int_to_prompt(0);
4404
add_int_to_prompt(t->tm_sec);
4407
processed_prompt->append(day_names[t->tm_wday]);
4410
processed_prompt->append(t->tm_hour < 12 ? "am" : "pm");
4413
add_int_to_prompt(t->tm_mon+1);
4416
processed_prompt->append(month_names[t->tm_mon]);
4419
processed_prompt->append("'");
4422
processed_prompt->append("\"");
4425
processed_prompt->append(";");
4428
processed_prompt->append("\t");
4431
processed_prompt->append(delimiter_str);
4434
processed_prompt->append(c, 1);
4438
return processed_prompt->c_str();
4442
static void add_int_to_prompt(int toadd)
4444
ostringstream buffer;
4446
processed_prompt->append(buffer.str().c_str());
4449
static void init_username()
4452
free(full_username);
4453
free(part_username);
4455
drizzle_result_st *result;
4456
if (!drizzleclient_query(&drizzle,"select USER()") &&
4457
(result=drizzleclient_use_result(&drizzle)))
4459
drizzle_row_t cur=drizzleclient_fetch_row(result);
4460
full_username= strdup(cur[0]);
4461
part_username= strdup(strtok(cur[0],"@"));
4462
(void) drizzleclient_fetch_row(result); // Read eof
4467
static int com_prompt(string *, const char *line)
4469
const char *ptr=strchr(line, ' ');
4471
tee_fprintf(stdout, "Returning to default PROMPT of %s\n",
4474
char * tmpptr= strdup(ptr ? ptr+1 : default_prompt);
4476
tee_fprintf(stdout, "Memory allocation error. Not changing prompt\n");
4479
free(current_prompt);
4480
current_prompt= tmpptr;
4481
tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
4487
strcont(str, set) if str contanies any character in the string set.
4488
The result is the position of the first found character in str, or NULL
4489
if there isn't anything found.
4492
static const char * strcont(register const char *str, register const char *set)
4494
register const char * start = (const char *) set;
4501
return ((const char*) str);