00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <config.h>
00038 #include <libdrizzle-2.0/libdrizzle.h>
00039
00040 #include "server_detect.h"
00041 #include "get_password.h"
00042
00043 #include <boost/date_time/posix_time/posix_time.hpp>
00044
00045 #include <cerrno>
00046 #include <string>
00047 #include <drizzled/gettext.h>
00048 #include <iostream>
00049 #include <fstream>
00050 #include <map>
00051 #include <algorithm>
00052 #include <limits.h>
00053 #include <cassert>
00054 #include <stdarg.h>
00055 #include <math.h>
00056 #include <memory>
00057 #include <client/linebuffer.h>
00058 #include <signal.h>
00059 #include <sys/ioctl.h>
00060 #include <drizzled/configmake.h>
00061 #include <drizzled/utf8/utf8.h>
00062 #include <cstdlib>
00063
00064 #if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
00065 #include <curses.h>
00066 #ifdef __sun
00067 #undef clear
00068 #undef erase
00069 #endif
00070 #include <term.h>
00071 #else
00072 #if defined(HAVE_TERMIOS_H)
00073 #include <termios.h>
00074 #include <unistd.h>
00075 #elif defined(HAVE_TERMBITS_H)
00076 #include <termbits.h>
00077 #elif defined(HAVE_ASM_TERMBITS_H) && (!defined __GLIBC__ || !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
00078 #include <asm/termbits.h>
00079 #endif
00080 #if defined(HAVE_TERMCAP_H)
00081 #include <termcap.h>
00082 #else
00083 #ifdef HAVE_CURSES_H
00084 #include <curses.h>
00085 #endif
00086 #undef SYSV // hack to avoid syntax error
00087 #ifdef HAVE_TERM_H
00088 #include <term.h>
00089 #endif
00090 #endif
00091 #endif
00092
00093 #ifdef HAVE_LIBREADLINE
00094 # if defined(HAVE_READLINE_READLINE_H)
00095 # include <readline/readline.h>
00096 # elif defined(HAVE_READLINE_H)
00097 # include <readline.h>
00098 # else
00099 extern char *readline ();
00100 # endif
00101 char *cmdline = NULL;
00102 #else
00103
00104 # error Readline Required
00105 #endif
00106
00107 #ifdef HAVE_READLINE_HISTORY
00108 # if defined(HAVE_READLINE_HISTORY_H)
00109 # include <readline/history.h>
00110 # elif defined(HAVE_HISTORY_H)
00111 # include <history.h>
00112 # else
00113 extern void add_history ();
00114 extern int write_history ();
00115 extern int read_history ();
00116 # endif
00117
00118 #endif
00119
00123 #ifndef HAVE_RL_COMPLETION
00124 typedef char **rl_completion_func_t(const char *, int, int);
00125 #define rl_completion_matches(str, func) \
00126 completion_matches((char *)str, (CPFunction *)func)
00127 #endif
00128
00129 #ifdef HAVE_RL_COMPENTRY
00130 # ifdef HAVE_WORKING_RL_COMPENTRY
00131 typedef rl_compentry_func_t drizzle_compentry_func_t;
00132 # else
00133
00134
00135
00136
00137 typedef Function drizzle_compentry_func_t;
00138 # endif
00139 #else
00140 typedef Function drizzle_compentry_func_t;
00141 #endif
00142
00143 #if defined(HAVE_LOCALE_H)
00144 #include <locale.h>
00145 #endif
00146
00147
00148
00149 #if !defined(HAVE_VIDATTR)
00150 #undef vidattr
00151 #define vidattr(A) {} // Can't get this to work
00152 #endif
00153 #include <boost/program_options.hpp>
00154 #include <boost/scoped_ptr.hpp>
00155 #include <drizzled/program_options/config_file.h>
00156
00157 #include "user_detect.h"
00158
00159 using namespace std;
00160 namespace po=boost::program_options;
00161 namespace dpo=drizzled::program_options;
00162
00163
00164 const uint32_t MAX_COLUMN_LENGTH= 1024;
00165
00166
00167 const int MAX_SERVER_VERSION_LENGTH= 128;
00168
00169
00170 drizzle_con_options_t global_con_options= DRIZZLE_CON_NONE;
00171
00172 #define PROMPT_CHAR '\\'
00173
00174 class Status
00175 {
00176 public:
00177
00178 Status(int in_exit_status,
00179 uint32_t in_query_start_line,
00180 char *in_file_name,
00181 LineBuffer *in_line_buff,
00182 bool in_batch,
00183 bool in_add_to_history)
00184 :
00185 exit_status(in_exit_status),
00186 query_start_line(in_query_start_line),
00187 file_name(in_file_name),
00188 line_buff(in_line_buff),
00189 batch(in_batch),
00190 add_to_history(in_add_to_history)
00191 {}
00192
00193 Status() :
00194 exit_status(0),
00195 query_start_line(0),
00196 file_name(NULL),
00197 line_buff(NULL),
00198 batch(false),
00199 add_to_history(false)
00200 {}
00201
00202 int getExitStatus() const
00203 {
00204 return exit_status;
00205 }
00206
00207 uint32_t getQueryStartLine() const
00208 {
00209 return query_start_line;
00210 }
00211
00212 const char *getFileName() const
00213 {
00214 return file_name;
00215 }
00216
00217 LineBuffer *getLineBuff() const
00218 {
00219 return line_buff;
00220 }
00221
00222 bool getBatch() const
00223 {
00224 return batch;
00225 }
00226
00227 bool getAddToHistory() const
00228 {
00229 return add_to_history;
00230 }
00231
00232 void setExitStatus(int in_exit_status)
00233 {
00234 exit_status= in_exit_status;
00235 }
00236
00237 void setQueryStartLine(uint32_t in_query_start_line)
00238 {
00239 query_start_line= in_query_start_line;
00240 }
00241
00242 void setFileName(char *in_file_name)
00243 {
00244 file_name= in_file_name;
00245 }
00246
00247 void setLineBuff(int max_size, FILE *file=NULL)
00248 {
00249 line_buff= new LineBuffer(max_size, file);
00250 }
00251
00252 void setLineBuff(LineBuffer *in_line_buff)
00253 {
00254 line_buff= in_line_buff;
00255 }
00256
00257 void setBatch(bool in_batch)
00258 {
00259 batch= in_batch;
00260 }
00261
00262 void setAddToHistory(bool in_add_to_history)
00263 {
00264 add_to_history= in_add_to_history;
00265 }
00266
00267 private:
00268 int exit_status;
00269 uint32_t query_start_line;
00270 char *file_name;
00271 LineBuffer *line_buff;
00272 bool batch,add_to_history;
00273 };
00274
00275 static map<string, string>::iterator completion_iter;
00276 static map<string, string>::iterator completion_end;
00277 static map<string, string> completion_map;
00278 static string completion_string;
00279
00280
00281 enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
00282 typedef enum enum_info_type INFO_TYPE;
00283
00284 static drizzle_st *drizzle= NULL;
00285 static drizzle_con_st *con= NULL;
00286 static bool ignore_errors= false, quick= false,
00287 connected= false, opt_raw_data= false, unbuffered= false,
00288 output_tables= false, opt_rehash= true, skip_updates= false,
00289 safe_updates= false, one_database= false,
00290 opt_shutdown= false, opt_ping= false,
00291 vertical= false, line_numbers= true, column_names= true,
00292 opt_nopager= true, opt_outfile= false, named_cmds= false,
00293 opt_nobeep= false, opt_reconnect= true,
00294 opt_secure_auth= false,
00295 default_pager_set= false, opt_sigint_ignore= false,
00296 auto_vertical_output= false,
00297 show_warnings= false, executing_query= false, interrupted_query= false,
00298 use_drizzle_protocol= false, opt_local_infile;
00299 static uint32_t opt_kill= 0;
00300 static uint32_t show_progress_size= 0;
00301 static bool column_types_flag;
00302 static bool preserve_comments= false;
00303 static uint32_t opt_max_input_line;
00304 static uint32_t opt_drizzle_port= 0;
00305 static int opt_silent, verbose= 0;
00306 static char *histfile;
00307 static char *histfile_tmp;
00308 static string *glob_buffer;
00309 static string *processed_prompt= NULL;
00310 static char *default_prompt= NULL;
00311 static char *full_username= NULL,*part_username= NULL;
00312 static Status status;
00313 static uint32_t select_limit;
00314 static uint32_t max_join_size;
00315 static uint32_t opt_connect_timeout= 0;
00316 static ServerDetect::server_type server_type= ServerDetect::SERVER_UNKNOWN_FOUND;
00317 std::string current_db,
00318 delimiter_str,
00319 current_host,
00320 current_prompt,
00321 current_user,
00322 opt_verbose,
00323 current_password,
00324 opt_password,
00325 opt_protocol;
00326
00327 static const char* get_day_name(int day_of_week)
00328 {
00329 switch(day_of_week)
00330 {
00331 case 0:
00332 return _("Sun");
00333 case 1:
00334 return _("Mon");
00335 case 2:
00336 return _("Tue");
00337 case 3:
00338 return _("Wed");
00339 case 4:
00340 return _("Thu");
00341 case 5:
00342 return _("Fri");
00343 case 6:
00344 return _("Sat");
00345 }
00346
00347 return NULL;
00348 }
00349
00350 static const char* get_month_name(int month)
00351 {
00352 switch(month)
00353 {
00354 case 0:
00355 return _("Jan");
00356 case 1:
00357 return _("Feb");
00358 case 2:
00359 return _("Mar");
00360 case 3:
00361 return _("Apr");
00362 case 4:
00363 return _("May");
00364 case 5:
00365 return _("Jun");
00366 case 6:
00367 return _("Jul");
00368 case 7:
00369 return _("Aug");
00370 case 8:
00371 return _("Sep");
00372 case 9:
00373 return _("Oct");
00374 case 10:
00375 return _("Nov");
00376 case 11:
00377 return _("Dec");
00378 }
00379
00380 return NULL;
00381 }
00382
00383
00384 #define FN_REFLEN 512
00385
00386 static string default_pager("");
00387 static string pager("");
00388 static string outfile("");
00389 static FILE *PAGER, *OUTFILE;
00390 static uint32_t prompt_counter;
00391 static const char *delimiter= NULL;
00392 static uint32_t delimiter_length= 1;
00393 unsigned short terminal_width= 80;
00394
00395 int drizzleclient_real_query_for_lazy(const char *buf, size_t length, drizzle_result_st *result, uint32_t *error_code);
00396 int drizzleclient_store_result_for_lazy(drizzle_result_st *result);
00397
00398 void tee_fprintf(FILE *file, const char *fmt, ...);
00399 void tee_fputs(const char *s, FILE *file);
00400 void tee_puts(const char *s, FILE *file);
00401 void tee_putc(int c, FILE *file);
00402 static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
00403
00404 static int process_options(void);
00405 static int com_quit(string *str,const char*),
00406 com_go(string *str,const char*), com_ego(string *str,const char*),
00407 com_print(string *str,const char*),
00408 com_help(string *str,const char*), com_clear(string *str,const char*),
00409 com_connect(string *str,const char*), com_status(string *str,const char*),
00410 com_use(string *str,const char*), com_source(string *str, const char*),
00411 com_shutdown(string *str,const char*),
00412 com_rehash(string *str, const char*), com_tee(string *str, const char*),
00413 com_notee(string *str, const char*),
00414 com_prompt(string *str, const char*), com_delimiter(string *str, const char*),
00415 com_warnings(string *str, const char*), com_nowarnings(string *str, const char*),
00416 com_nopager(string *str, const char*), com_pager(string *str, const char*);
00417
00418 static int read_and_execute(bool interactive);
00419 static int sql_connect(const string &host, const string &database, const string &user, const string &password);
00420 static const char *server_version_string(drizzle_con_st *con);
00421 static int put_info(const char *str,INFO_TYPE info,uint32_t error,
00422 const char *sql_state);
00423 static int put_error(drizzle_con_st *con, drizzle_result_st *res);
00424 static void safe_put_field(const char *pos,uint32_t length);
00425 static void init_pager(void);
00426 static void end_pager(void);
00427 static void init_tee(const char *);
00428 static void end_tee(void);
00429 static const char* construct_prompt(void);
00430 static char *get_arg(char *line, bool get_next_arg);
00431 static void init_username(void);
00432 static void add_int_to_prompt(int toadd);
00433 static int get_result_width(drizzle_result_st *res);
00434 static int get_field_disp_length(drizzle_column_st * field);
00435 static const char * strcont(const char *str, const char *set);
00436
00437
00438
00439 class Commands
00440 {
00441 private:
00442 const char *name;
00443 char cmd_char;
00444 public:
00445 Commands(const char *in_name,
00446 char in_cmd_char,
00447 int (*in_func)(string *str,const char *name),
00448 bool in_takes_params,
00449 const char *in_doc) :
00450 name(in_name),
00451 cmd_char(in_cmd_char),
00452 func(in_func),
00453 takes_params(in_takes_params),
00454 doc(in_doc)
00455 {}
00456
00457 Commands() :
00458 name(),
00459 cmd_char(),
00460 func(NULL),
00461 takes_params(false),
00462 doc()
00463 {}
00464
00465 int (*func)(string *str,const char *);
00466
00467 const char *getName() const
00468 {
00469 return name;
00470 }
00471
00472 char getCmdChar() const
00473 {
00474 return cmd_char;
00475 }
00476
00477 bool getTakesParams() const
00478 {
00479 return takes_params;
00480 }
00481
00482 const char *getDoc() const
00483 {
00484 return doc;
00485 }
00486
00487 void setName(const char *in_name)
00488 {
00489 name= in_name;
00490 }
00491
00492 void setCmdChar(char in_cmd_char)
00493 {
00494 cmd_char= in_cmd_char;
00495 }
00496
00497 void setTakesParams(bool in_takes_params)
00498 {
00499 takes_params= in_takes_params;
00500 }
00501
00502 void setDoc(const char *in_doc)
00503 {
00504 doc= in_doc;
00505 }
00506
00507 private:
00508 bool takes_params;
00509 const char *doc;
00510 };
00511
00512
00513 static Commands commands[] = {
00514 Commands( "?", '?', com_help, 0, N_("Synonym for `help'.") ),
00515 Commands( "clear", 'c', com_clear, 0, N_("Clear command.")),
00516 Commands( "connect",'r', com_connect,1,
00517 N_("Reconnect to the server. Optional arguments are db and host.")),
00518 Commands( "delimiter", 'd', com_delimiter, 1,
00519 N_("Set statement delimiter. NOTE: Takes the rest of the line as new delimiter.") ),
00520 Commands( "ego", 'G', com_ego, 0,
00521 N_("Send command to drizzle server, display result vertically.")),
00522 Commands( "exit", 'q', com_quit, 0, N_("Exit drizzle. Same as quit.")),
00523 Commands( "go", 'g', com_go, 0, N_("Send command to drizzle server.") ),
00524 Commands( "help", 'h', com_help, 0, N_("Display this help.") ),
00525 Commands( "nopager",'n', com_nopager,0, N_("Disable pager, print to stdout.") ),
00526 Commands( "notee", 't', com_notee, 0, N_("Don't write into outfile.") ),
00527 Commands( "pager", 'P', com_pager, 1,
00528 N_("Set PAGER [to_pager]. Print the query results via PAGER.") ),
00529 Commands( "print", 'p', com_print, 0, N_("Print current command.") ),
00530 Commands( "prompt", 'R', com_prompt, 1, N_("Change your drizzle prompt.")),
00531 Commands( "quit", 'q', com_quit, 0, N_("Quit drizzle.") ),
00532 Commands( "rehash", '#', com_rehash, 0, N_("Rebuild completion hash.") ),
00533 Commands( "source", '.', com_source, 1,
00534 N_("Execute an SQL script file. Takes a file name as an argument.")),
00535 Commands( "status", 's', com_status, 0, N_("Get status information from the server.")),
00536 Commands( "tee", 'T', com_tee, 1,
00537 N_("Set outfile [to_outfile]. Append everything into given outfile.") ),
00538 Commands( "use", 'u', com_use, 1,
00539 N_("Use another schema. Takes schema name as argument.") ),
00540 Commands( "shutdown", 'Q', com_shutdown, false,
00541 N_("Shutdown the instance you are connected too.") ),
00542 Commands( "warnings", 'W', com_warnings, false,
00543 N_("Show warnings after every statement.") ),
00544 Commands( "nowarning", 'w', com_nowarnings, 0,
00545 N_("Don't show warnings after every statement.") ),
00546
00547 Commands( "create table", 0, 0, 0, ""),
00548 Commands( "create database", 0, 0, 0, ""),
00549 Commands( "show databases", 0, 0, 0, ""),
00550 Commands( "show fields from", 0, 0, 0, ""),
00551 Commands( "show keys from", 0, 0, 0, ""),
00552 Commands( "show tables", 0, 0, 0, ""),
00553 Commands( "load data from", 0, 0, 0, ""),
00554 Commands( "alter table", 0, 0, 0, ""),
00555 Commands( "set option", 0, 0, 0, ""),
00556 Commands( "lock tables", 0, 0, 0, ""),
00557 Commands( "unlock tables", 0, 0, 0, ""),
00558
00559 Commands( "ACTION", 0, 0, 0, ""),
00560 Commands( "ADD", 0, 0, 0, ""),
00561 Commands( "AFTER", 0, 0, 0, ""),
00562 Commands( "AGAINST", 0, 0, 0, ""),
00563 Commands( "AGGREGATE", 0, 0, 0, ""),
00564 Commands( "ALL", 0, 0, 0, ""),
00565 Commands( "ALGORITHM", 0, 0, 0, ""),
00566 Commands( "ALTER", 0, 0, 0, ""),
00567 Commands( "ANALYZE", 0, 0, 0, ""),
00568 Commands( "AND", 0, 0, 0, ""),
00569 Commands( "ANY", 0, 0, 0, ""),
00570 Commands( "AS", 0, 0, 0, ""),
00571 Commands( "ASC", 0, 0, 0, ""),
00572 Commands( "ASCII", 0, 0, 0, ""),
00573 Commands( "ASENSITIVE", 0, 0, 0, ""),
00574 Commands( "AUTO_INCREMENT", 0, 0, 0, ""),
00575 Commands( "AVG", 0, 0, 0, ""),
00576 Commands( "AVG_ROW_LENGTH", 0, 0, 0, ""),
00577 Commands( "BEFORE", 0, 0, 0, ""),
00578 Commands( "BEGIN", 0, 0, 0, ""),
00579 Commands( "BETWEEN", 0, 0, 0, ""),
00580 Commands( "BIGINT", 0, 0, 0, ""),
00581 Commands( "BINARY", 0, 0, 0, ""),
00582 Commands( "BIT", 0, 0, 0, ""),
00583 Commands( "BLOB", 0, 0, 0, ""),
00584 Commands( "BOOL", 0, 0, 0, ""),
00585 Commands( "BOOLEAN", 0, 0, 0, ""),
00586 Commands( "BOTH", 0, 0, 0, ""),
00587 Commands( "BTREE", 0, 0, 0, ""),
00588 Commands( "BY", 0, 0, 0, ""),
00589 Commands( "BYTE", 0, 0, 0, ""),
00590 Commands( "CACHE", 0, 0, 0, ""),
00591 Commands( "CALL", 0, 0, 0, ""),
00592 Commands( "CASCADE", 0, 0, 0, ""),
00593 Commands( "CASCADED", 0, 0, 0, ""),
00594 Commands( "CASE", 0, 0, 0, ""),
00595 Commands( "CHAIN", 0, 0, 0, ""),
00596 Commands( "CHANGE", 0, 0, 0, ""),
00597 Commands( "CHANGED", 0, 0, 0, ""),
00598 Commands( "CHAR", 0, 0, 0, ""),
00599 Commands( "CHARACTER", 0, 0, 0, ""),
00600 Commands( "CHECK", 0, 0, 0, ""),
00601 Commands( "CHECKSUM", 0, 0, 0, ""),
00602 Commands( "CLIENT", 0, 0, 0, ""),
00603 Commands( "CLOSE", 0, 0, 0, ""),
00604 Commands( "COLLATE", 0, 0, 0, ""),
00605 Commands( "COLLATION", 0, 0, 0, ""),
00606 Commands( "COLUMN", 0, 0, 0, ""),
00607 Commands( "COLUMNS", 0, 0, 0, ""),
00608 Commands( "COMMENT", 0, 0, 0, ""),
00609 Commands( "COMMIT", 0, 0, 0, ""),
00610 Commands( "COMMITTED", 0, 0, 0, ""),
00611 Commands( "COMPACT", 0, 0, 0, ""),
00612 Commands( "COMPRESSED", 0, 0, 0, ""),
00613 Commands( "CONCURRENT", 0, 0, 0, ""),
00614 Commands( "CONDITION", 0, 0, 0, ""),
00615 Commands( "CONNECTION", 0, 0, 0, ""),
00616 Commands( "CONSISTENT", 0, 0, 0, ""),
00617 Commands( "CONSTRAINT", 0, 0, 0, ""),
00618 Commands( "CONTAINS", 0, 0, 0, ""),
00619 Commands( "CONTINUE", 0, 0, 0, ""),
00620 Commands( "CONVERT", 0, 0, 0, ""),
00621 Commands( "CREATE", 0, 0, 0, ""),
00622 Commands( "CROSS", 0, 0, 0, ""),
00623 Commands( "CUBE", 0, 0, 0, ""),
00624 Commands( "CURRENT_DATE", 0, 0, 0, ""),
00625 Commands( "CURRENT_TIMESTAMP", 0, 0, 0, ""),
00626 Commands( "CURRENT_USER", 0, 0, 0, ""),
00627 Commands( "CURSOR", 0, 0, 0, ""),
00628 Commands( "DATA", 0, 0, 0, ""),
00629 Commands( "DATABASE", 0, 0, 0, ""),
00630 Commands( "DATABASES", 0, 0, 0, ""),
00631 Commands( "DATE", 0, 0, 0, ""),
00632 Commands( "DATETIME", 0, 0, 0, ""),
00633 Commands( "DAY", 0, 0, 0, ""),
00634 Commands( "DAY_HOUR", 0, 0, 0, ""),
00635 Commands( "DAY_MICROSECOND", 0, 0, 0, ""),
00636 Commands( "DAY_MINUTE", 0, 0, 0, ""),
00637 Commands( "DAY_SECOND", 0, 0, 0, ""),
00638 Commands( "DEALLOCATE", 0, 0, 0, ""),
00639 Commands( "DEC", 0, 0, 0, ""),
00640 Commands( "DECIMAL", 0, 0, 0, ""),
00641 Commands( "DECLARE", 0, 0, 0, ""),
00642 Commands( "DEFAULT", 0, 0, 0, ""),
00643 Commands( "DEFINER", 0, 0, 0, ""),
00644 Commands( "DELAYED", 0, 0, 0, ""),
00645 Commands( "DELETE", 0, 0, 0, ""),
00646 Commands( "DESC", 0, 0, 0, ""),
00647 Commands( "DESCRIBE", 0, 0, 0, ""),
00648 Commands( "DETERMINISTIC", 0, 0, 0, ""),
00649 Commands( "DISABLE", 0, 0, 0, ""),
00650 Commands( "DISCARD", 0, 0, 0, ""),
00651 Commands( "DISTINCT", 0, 0, 0, ""),
00652 Commands( "DISTINCTROW", 0, 0, 0, ""),
00653 Commands( "DIV", 0, 0, 0, ""),
00654 Commands( "DOUBLE", 0, 0, 0, ""),
00655 Commands( "DROP", 0, 0, 0, ""),
00656 Commands( "DUMPFILE", 0, 0, 0, ""),
00657 Commands( "DUPLICATE", 0, 0, 0, ""),
00658 Commands( "DYNAMIC", 0, 0, 0, ""),
00659 Commands( "EACH", 0, 0, 0, ""),
00660 Commands( "ELSE", 0, 0, 0, ""),
00661 Commands( "ELSEIF", 0, 0, 0, ""),
00662 Commands( "ENABLE", 0, 0, 0, ""),
00663 Commands( "ENCLOSED", 0, 0, 0, ""),
00664 Commands( "END", 0, 0, 0, ""),
00665 Commands( "ENGINE", 0, 0, 0, ""),
00666 Commands( "ENGINES", 0, 0, 0, ""),
00667 Commands( "ENUM", 0, 0, 0, ""),
00668 Commands( "ERRORS", 0, 0, 0, ""),
00669 Commands( "ESCAPE", 0, 0, 0, ""),
00670 Commands( "ESCAPED", 0, 0, 0, ""),
00671 Commands( "EXISTS", 0, 0, 0, ""),
00672 Commands( "EXIT", 0, 0, 0, ""),
00673 Commands( "EXPLAIN", 0, 0, 0, ""),
00674 Commands( "EXTENDED", 0, 0, 0, ""),
00675 Commands( "FALSE", 0, 0, 0, ""),
00676 Commands( "FAST", 0, 0, 0, ""),
00677 Commands( "FETCH", 0, 0, 0, ""),
00678 Commands( "FIELDS", 0, 0, 0, ""),
00679 Commands( "FILE", 0, 0, 0, ""),
00680 Commands( "FIRST", 0, 0, 0, ""),
00681 Commands( "FIXED", 0, 0, 0, ""),
00682 Commands( "FLOAT", 0, 0, 0, ""),
00683 Commands( "FLOAT4", 0, 0, 0, ""),
00684 Commands( "FLOAT8", 0, 0, 0, ""),
00685 Commands( "FLUSH", 0, 0, 0, ""),
00686 Commands( "FOR", 0, 0, 0, ""),
00687 Commands( "FORCE", 0, 0, 0, ""),
00688 Commands( "FOREIGN", 0, 0, 0, ""),
00689 Commands( "FOUND", 0, 0, 0, ""),
00690 Commands( "FRAC_SECOND", 0, 0, 0, ""),
00691 Commands( "FROM", 0, 0, 0, ""),
00692 Commands( "FULL", 0, 0, 0, ""),
00693 Commands( "FUNCTION", 0, 0, 0, ""),
00694 Commands( "GLOBAL", 0, 0, 0, ""),
00695 Commands( "GRANT", 0, 0, 0, ""),
00696 Commands( "GRANTS", 0, 0, 0, ""),
00697 Commands( "GROUP", 0, 0, 0, ""),
00698 Commands( "HANDLER", 0, 0, 0, ""),
00699 Commands( "HASH", 0, 0, 0, ""),
00700 Commands( "HAVING", 0, 0, 0, ""),
00701 Commands( "HELP", 0, 0, 0, ""),
00702 Commands( "HIGH_PRIORITY", 0, 0, 0, ""),
00703 Commands( "HOSTS", 0, 0, 0, ""),
00704 Commands( "HOUR", 0, 0, 0, ""),
00705 Commands( "HOUR_MICROSECOND", 0, 0, 0, ""),
00706 Commands( "HOUR_MINUTE", 0, 0, 0, ""),
00707 Commands( "HOUR_SECOND", 0, 0, 0, ""),
00708 Commands( "IDENTIFIED", 0, 0, 0, ""),
00709 Commands( "IF", 0, 0, 0, ""),
00710 Commands( "IGNORE", 0, 0, 0, ""),
00711 Commands( "IMPORT", 0, 0, 0, ""),
00712 Commands( "IN", 0, 0, 0, ""),
00713 Commands( "INDEX", 0, 0, 0, ""),
00714 Commands( "INDEXES", 0, 0, 0, ""),
00715 Commands( "INFILE", 0, 0, 0, ""),
00716 Commands( "INNER", 0, 0, 0, ""),
00717 Commands( "INNOBASE", 0, 0, 0, ""),
00718 Commands( "INNODB", 0, 0, 0, ""),
00719 Commands( "INOUT", 0, 0, 0, ""),
00720 Commands( "INSENSITIVE", 0, 0, 0, ""),
00721 Commands( "INSERT", 0, 0, 0, ""),
00722 Commands( "INSERT_METHOD", 0, 0, 0, ""),
00723 Commands( "INT", 0, 0, 0, ""),
00724 Commands( "INT1", 0, 0, 0, ""),
00725 Commands( "INT2", 0, 0, 0, ""),
00726 Commands( "INT3", 0, 0, 0, ""),
00727 Commands( "INT4", 0, 0, 0, ""),
00728 Commands( "INT8", 0, 0, 0, ""),
00729 Commands( "INTEGER", 0, 0, 0, ""),
00730 Commands( "INTERVAL", 0, 0, 0, ""),
00731 Commands( "INTO", 0, 0, 0, ""),
00732 Commands( "IO_THREAD", 0, 0, 0, ""),
00733 Commands( "IS", 0, 0, 0, ""),
00734 Commands( "ISOLATION", 0, 0, 0, ""),
00735 Commands( "ISSUER", 0, 0, 0, ""),
00736 Commands( "ITERATE", 0, 0, 0, ""),
00737 Commands( "INVOKER", 0, 0, 0, ""),
00738 Commands( "JOIN", 0, 0, 0, ""),
00739 Commands( "KEY", 0, 0, 0, ""),
00740 Commands( "KEYS", 0, 0, 0, ""),
00741 Commands( "KILL", 0, 0, 0, ""),
00742 Commands( "LANGUAGE", 0, 0, 0, ""),
00743 Commands( "LAST", 0, 0, 0, ""),
00744 Commands( "LEADING", 0, 0, 0, ""),
00745 Commands( "LEAVE", 0, 0, 0, ""),
00746 Commands( "LEAVES", 0, 0, 0, ""),
00747 Commands( "LEFT", 0, 0, 0, ""),
00748 Commands( "LEVEL", 0, 0, 0, ""),
00749 Commands( "LIKE", 0, 0, 0, ""),
00750 Commands( "LIMIT", 0, 0, 0, ""),
00751 Commands( "LINES", 0, 0, 0, ""),
00752 Commands( "LINESTRING", 0, 0, 0, ""),
00753 Commands( "LOAD", 0, 0, 0, ""),
00754 Commands( "LOCAL", 0, 0, 0, ""),
00755 Commands( "LOCALTIMESTAMP", 0, 0, 0, ""),
00756 Commands( "LOCK", 0, 0, 0, ""),
00757 Commands( "LOCKS", 0, 0, 0, ""),
00758 Commands( "LOGS", 0, 0, 0, ""),
00759 Commands( "LONG", 0, 0, 0, ""),
00760 Commands( "LOOP", 0, 0, 0, ""),
00761 Commands( "MATCH", 0, 0, 0, ""),
00762 Commands( "MAX_CONNECTIONS_PER_HOUR", 0, 0, 0, ""),
00763 Commands( "MAX_QUERIES_PER_HOUR", 0, 0, 0, ""),
00764 Commands( "MAX_ROWS", 0, 0, 0, ""),
00765 Commands( "MAX_UPDATES_PER_HOUR", 0, 0, 0, ""),
00766 Commands( "MAX_USER_CONNECTIONS", 0, 0, 0, ""),
00767 Commands( "MEDIUM", 0, 0, 0, ""),
00768 Commands( "MERGE", 0, 0, 0, ""),
00769 Commands( "MICROSECOND", 0, 0, 0, ""),
00770 Commands( "MIGRATE", 0, 0, 0, ""),
00771 Commands( "MINUTE", 0, 0, 0, ""),
00772 Commands( "MINUTE_MICROSECOND", 0, 0, 0, ""),
00773 Commands( "MINUTE_SECOND", 0, 0, 0, ""),
00774 Commands( "MIN_ROWS", 0, 0, 0, ""),
00775 Commands( "MOD", 0, 0, 0, ""),
00776 Commands( "MODE", 0, 0, 0, ""),
00777 Commands( "MODIFIES", 0, 0, 0, ""),
00778 Commands( "MODIFY", 0, 0, 0, ""),
00779 Commands( "MONTH", 0, 0, 0, ""),
00780 Commands( "MULTILINESTRING", 0, 0, 0, ""),
00781 Commands( "MULTIPOINT", 0, 0, 0, ""),
00782 Commands( "MULTIPOLYGON", 0, 0, 0, ""),
00783 Commands( "MUTEX", 0, 0, 0, ""),
00784 Commands( "NAME", 0, 0, 0, ""),
00785 Commands( "NAMES", 0, 0, 0, ""),
00786 Commands( "NATIONAL", 0, 0, 0, ""),
00787 Commands( "NATURAL", 0, 0, 0, ""),
00788 Commands( "NCHAR", 0, 0, 0, ""),
00789 Commands( "NEW", 0, 0, 0, ""),
00790 Commands( "NEXT", 0, 0, 0, ""),
00791 Commands( "NO", 0, 0, 0, ""),
00792 Commands( "NONE", 0, 0, 0, ""),
00793 Commands( "NOT", 0, 0, 0, ""),
00794 Commands( "NULL", 0, 0, 0, ""),
00795 Commands( "NUMERIC", 0, 0, 0, ""),
00796 Commands( "NVARCHAR", 0, 0, 0, ""),
00797 Commands( "OFFSET", 0, 0, 0, ""),
00798 Commands( "ON", 0, 0, 0, ""),
00799 Commands( "ONE", 0, 0, 0, ""),
00800 Commands( "ONE_SHOT", 0, 0, 0, ""),
00801 Commands( "OPEN", 0, 0, 0, ""),
00802 Commands( "OPTIMIZE", 0, 0, 0, ""),
00803 Commands( "OPTION", 0, 0, 0, ""),
00804 Commands( "OPTIONALLY", 0, 0, 0, ""),
00805 Commands( "OR", 0, 0, 0, ""),
00806 Commands( "ORDER", 0, 0, 0, ""),
00807 Commands( "OUT", 0, 0, 0, ""),
00808 Commands( "OUTER", 0, 0, 0, ""),
00809 Commands( "OUTFILE", 0, 0, 0, ""),
00810 Commands( "PACK_KEYS", 0, 0, 0, ""),
00811 Commands( "PARTIAL", 0, 0, 0, ""),
00812 Commands( "PASSWORD", 0, 0, 0, ""),
00813 Commands( "PHASE", 0, 0, 0, ""),
00814 Commands( "PRECISION", 0, 0, 0, ""),
00815 Commands( "PREPARE", 0, 0, 0, ""),
00816 Commands( "PREV", 0, 0, 0, ""),
00817 Commands( "PRIMARY", 0, 0, 0, ""),
00818 Commands( "PRIVILEGES", 0, 0, 0, ""),
00819 Commands( "PROCEDURE", 0, 0, 0, ""),
00820 Commands( "PROCESS", 0, 0, 0, ""),
00821 Commands( "PROCESSLIST", 0, 0, 0, ""),
00822 Commands( "PURGE", 0, 0, 0, ""),
00823 Commands( "QUARTER", 0, 0, 0, ""),
00824 Commands( "QUERY", 0, 0, 0, ""),
00825 Commands( "QUICK", 0, 0, 0, ""),
00826 Commands( "READ", 0, 0, 0, ""),
00827 Commands( "READS", 0, 0, 0, ""),
00828 Commands( "REAL", 0, 0, 0, ""),
00829 Commands( "RECOVER", 0, 0, 0, ""),
00830 Commands( "REDUNDANT", 0, 0, 0, ""),
00831 Commands( "REFERENCES", 0, 0, 0, ""),
00832 Commands( "REGEXP", 0, 0, 0, ""),
00833 Commands( "RELEASE", 0, 0, 0, ""),
00834 Commands( "RELOAD", 0, 0, 0, ""),
00835 Commands( "RENAME", 0, 0, 0, ""),
00836 Commands( "REPAIR", 0, 0, 0, ""),
00837 Commands( "REPEATABLE", 0, 0, 0, ""),
00838 Commands( "REPLACE", 0, 0, 0, ""),
00839 Commands( "REPEAT", 0, 0, 0, ""),
00840 Commands( "REQUIRE", 0, 0, 0, ""),
00841 Commands( "RESET", 0, 0, 0, ""),
00842 Commands( "RESTORE", 0, 0, 0, ""),
00843 Commands( "RESTRICT", 0, 0, 0, ""),
00844 Commands( "RESUME", 0, 0, 0, ""),
00845 Commands( "RETURN", 0, 0, 0, ""),
00846 Commands( "RETURNS", 0, 0, 0, ""),
00847 Commands( "REVOKE", 0, 0, 0, ""),
00848 Commands( "RIGHT", 0, 0, 0, ""),
00849 Commands( "RLIKE", 0, 0, 0, ""),
00850 Commands( "ROLLBACK", 0, 0, 0, ""),
00851 Commands( "ROLLUP", 0, 0, 0, ""),
00852 Commands( "ROUTINE", 0, 0, 0, ""),
00853 Commands( "ROW", 0, 0, 0, ""),
00854 Commands( "ROWS", 0, 0, 0, ""),
00855 Commands( "ROW_FORMAT", 0, 0, 0, ""),
00856 Commands( "RTREE", 0, 0, 0, ""),
00857 Commands( "SAVEPOINT", 0, 0, 0, ""),
00858 Commands( "SCHEMA", 0, 0, 0, ""),
00859 Commands( "SCHEMAS", 0, 0, 0, ""),
00860 Commands( "SECOND", 0, 0, 0, ""),
00861 Commands( "SECOND_MICROSECOND", 0, 0, 0, ""),
00862 Commands( "SECURITY", 0, 0, 0, ""),
00863 Commands( "SELECT", 0, 0, 0, ""),
00864 Commands( "SENSITIVE", 0, 0, 0, ""),
00865 Commands( "SEPARATOR", 0, 0, 0, ""),
00866 Commands( "SERIAL", 0, 0, 0, ""),
00867 Commands( "SERIALIZABLE", 0, 0, 0, ""),
00868 Commands( "SESSION", 0, 0, 0, ""),
00869 Commands( "SET", 0, 0, 0, ""),
00870 Commands( "SHARE", 0, 0, 0, ""),
00871 Commands( "SHOW", 0, 0, 0, ""),
00872 Commands( "SHUTDOWN", 0, 0, 0, ""),
00873 Commands( "SIGNED", 0, 0, 0, ""),
00874 Commands( "SIMPLE", 0, 0, 0, ""),
00875 Commands( "SLAVE", 0, 0, 0, ""),
00876 Commands( "SNAPSHOT", 0, 0, 0, ""),
00877 Commands( "SOME", 0, 0, 0, ""),
00878 Commands( "SONAME", 0, 0, 0, ""),
00879 Commands( "SOUNDS", 0, 0, 0, ""),
00880 Commands( "SPATIAL", 0, 0, 0, ""),
00881 Commands( "SPECIFIC", 0, 0, 0, ""),
00882 Commands( "SQL", 0, 0, 0, ""),
00883 Commands( "SQLEXCEPTION", 0, 0, 0, ""),
00884 Commands( "SQLSTATE", 0, 0, 0, ""),
00885 Commands( "SQLWARNING", 0, 0, 0, ""),
00886 Commands( "SQL_BIG_RESULT", 0, 0, 0, ""),
00887 Commands( "SQL_BUFFER_RESULT", 0, 0, 0, ""),
00888 Commands( "SQL_CACHE", 0, 0, 0, ""),
00889 Commands( "SQL_CALC_FOUND_ROWS", 0, 0, 0, ""),
00890 Commands( "SQL_NO_CACHE", 0, 0, 0, ""),
00891 Commands( "SQL_SMALL_RESULT", 0, 0, 0, ""),
00892 Commands( "SQL_THREAD", 0, 0, 0, ""),
00893 Commands( "SQL_TSI_FRAC_SECOND", 0, 0, 0, ""),
00894 Commands( "SQL_TSI_SECOND", 0, 0, 0, ""),
00895 Commands( "SQL_TSI_MINUTE", 0, 0, 0, ""),
00896 Commands( "SQL_TSI_HOUR", 0, 0, 0, ""),
00897 Commands( "SQL_TSI_DAY", 0, 0, 0, ""),
00898 Commands( "SQL_TSI_WEEK", 0, 0, 0, ""),
00899 Commands( "SQL_TSI_MONTH", 0, 0, 0, ""),
00900 Commands( "SQL_TSI_QUARTER", 0, 0, 0, ""),
00901 Commands( "SQL_TSI_YEAR", 0, 0, 0, ""),
00902 Commands( "SSL", 0, 0, 0, ""),
00903 Commands( "START", 0, 0, 0, ""),
00904 Commands( "STARTING", 0, 0, 0, ""),
00905 Commands( "STATUS", 0, 0, 0, ""),
00906 Commands( "STOP", 0, 0, 0, ""),
00907 Commands( "STORAGE", 0, 0, 0, ""),
00908 Commands( "STRAIGHT_JOIN", 0, 0, 0, ""),
00909 Commands( "STRING", 0, 0, 0, ""),
00910 Commands( "STRIPED", 0, 0, 0, ""),
00911 Commands( "SUBJECT", 0, 0, 0, ""),
00912 Commands( "SUPER", 0, 0, 0, ""),
00913 Commands( "SUSPEND", 0, 0, 0, ""),
00914 Commands( "TABLE", 0, 0, 0, ""),
00915 Commands( "TABLES", 0, 0, 0, ""),
00916 Commands( "TABLESPACE", 0, 0, 0, ""),
00917 Commands( "TEMPORARY", 0, 0, 0, ""),
00918 Commands( "TEMPTABLE", 0, 0, 0, ""),
00919 Commands( "TERMINATED", 0, 0, 0, ""),
00920 Commands( "TEXT", 0, 0, 0, ""),
00921 Commands( "THEN", 0, 0, 0, ""),
00922 Commands( "TIMESTAMP", 0, 0, 0, ""),
00923 Commands( "TIMESTAMPADD", 0, 0, 0, ""),
00924 Commands( "TIMESTAMPDIFF", 0, 0, 0, ""),
00925 Commands( "TO", 0, 0, 0, ""),
00926 Commands( "TRAILING", 0, 0, 0, ""),
00927 Commands( "TRANSACTION", 0, 0, 0, ""),
00928 Commands( "TRUE", 0, 0, 0, ""),
00929 Commands( "TRUNCATE", 0, 0, 0, ""),
00930 Commands( "TYPE", 0, 0, 0, ""),
00931 Commands( "TYPES", 0, 0, 0, ""),
00932 Commands( "UNCOMMITTED", 0, 0, 0, ""),
00933 Commands( "UNDEFINED", 0, 0, 0, ""),
00934 Commands( "UNDO", 0, 0, 0, ""),
00935 Commands( "UNICODE", 0, 0, 0, ""),
00936 Commands( "UNION", 0, 0, 0, ""),
00937 Commands( "UNIQUE", 0, 0, 0, ""),
00938 Commands( "UNKNOWN", 0, 0, 0, ""),
00939 Commands( "UNLOCK", 0, 0, 0, ""),
00940 Commands( "UNTIL", 0, 0, 0, ""),
00941 Commands( "UPDATE", 0, 0, 0, ""),
00942 Commands( "UPGRADE", 0, 0, 0, ""),
00943 Commands( "USAGE", 0, 0, 0, ""),
00944 Commands( "USE", 0, 0, 0, ""),
00945 Commands( "USER", 0, 0, 0, ""),
00946 Commands( "USER_RESOURCES", 0, 0, 0, ""),
00947 Commands( "USING", 0, 0, 0, ""),
00948 Commands( "UTC_DATE", 0, 0, 0, ""),
00949 Commands( "UTC_TIMESTAMP", 0, 0, 0, ""),
00950 Commands( "VALUE", 0, 0, 0, ""),
00951 Commands( "VALUES", 0, 0, 0, ""),
00952 Commands( "VARBINARY", 0, 0, 0, ""),
00953 Commands( "VARCHAR", 0, 0, 0, ""),
00954 Commands( "VARCHARACTER", 0, 0, 0, ""),
00955 Commands( "VARIABLES", 0, 0, 0, ""),
00956 Commands( "VARYING", 0, 0, 0, ""),
00957 Commands( "WARNINGS", 0, 0, 0, ""),
00958 Commands( "WEEK", 0, 0, 0, ""),
00959 Commands( "WHEN", 0, 0, 0, ""),
00960 Commands( "WHERE", 0, 0, 0, ""),
00961 Commands( "WHILE", 0, 0, 0, ""),
00962 Commands( "VIEW", 0, 0, 0, ""),
00963 Commands( "WITH", 0, 0, 0, ""),
00964 Commands( "WORK", 0, 0, 0, ""),
00965 Commands( "WRITE", 0, 0, 0, ""),
00966 Commands( "XOR", 0, 0, 0, ""),
00967 Commands( "XA", 0, 0, 0, ""),
00968 Commands( "YEAR", 0, 0, 0, ""),
00969 Commands( "YEAR_MONTH", 0, 0, 0, ""),
00970 Commands( "ZEROFILL", 0, 0, 0, ""),
00971 Commands( "ABS", 0, 0, 0, ""),
00972 Commands( "ACOS", 0, 0, 0, ""),
00973 Commands( "ADDDATE", 0, 0, 0, ""),
00974 Commands( "AREA", 0, 0, 0, ""),
00975 Commands( "ASIN", 0, 0, 0, ""),
00976 Commands( "ASBINARY", 0, 0, 0, ""),
00977 Commands( "ASTEXT", 0, 0, 0, ""),
00978 Commands( "ATAN", 0, 0, 0, ""),
00979 Commands( "ATAN2", 0, 0, 0, ""),
00980 Commands( "BENCHMARK", 0, 0, 0, ""),
00981 Commands( "BIN", 0, 0, 0, ""),
00982 Commands( "BIT_OR", 0, 0, 0, ""),
00983 Commands( "BIT_AND", 0, 0, 0, ""),
00984 Commands( "BIT_XOR", 0, 0, 0, ""),
00985 Commands( "CAST", 0, 0, 0, ""),
00986 Commands( "CEIL", 0, 0, 0, ""),
00987 Commands( "CEILING", 0, 0, 0, ""),
00988 Commands( "CENTROID", 0, 0, 0, ""),
00989 Commands( "CHAR_LENGTH", 0, 0, 0, ""),
00990 Commands( "CHARACTER_LENGTH", 0, 0, 0, ""),
00991 Commands( "COALESCE", 0, 0, 0, ""),
00992 Commands( "COERCIBILITY", 0, 0, 0, ""),
00993 Commands( "COMPRESS", 0, 0, 0, ""),
00994 Commands( "CONCAT", 0, 0, 0, ""),
00995 Commands( "CONCAT_WS", 0, 0, 0, ""),
00996 Commands( "CONNECTION_ID", 0, 0, 0, ""),
00997 Commands( "CONV", 0, 0, 0, ""),
00998 Commands( "CONVERT_TZ", 0, 0, 0, ""),
00999 Commands( "COUNT", 0, 0, 0, ""),
01000 Commands( "COS", 0, 0, 0, ""),
01001 Commands( "COT", 0, 0, 0, ""),
01002 Commands( "CRC32", 0, 0, 0, ""),
01003 Commands( "CROSSES", 0, 0, 0, ""),
01004 Commands( "CURDATE", 0, 0, 0, ""),
01005 Commands( "DATE_ADD", 0, 0, 0, ""),
01006 Commands( "DATEDIFF", 0, 0, 0, ""),
01007 Commands( "DATE_FORMAT", 0, 0, 0, ""),
01008 Commands( "DATE_SUB", 0, 0, 0, ""),
01009 Commands( "DAYNAME", 0, 0, 0, ""),
01010 Commands( "DAYOFMONTH", 0, 0, 0, ""),
01011 Commands( "DAYOFWEEK", 0, 0, 0, ""),
01012 Commands( "DAYOFYEAR", 0, 0, 0, ""),
01013 Commands( "DECODE", 0, 0, 0, ""),
01014 Commands( "DEGREES", 0, 0, 0, ""),
01015 Commands( "DES_ENCRYPT", 0, 0, 0, ""),
01016 Commands( "DES_DECRYPT", 0, 0, 0, ""),
01017 Commands( "DIMENSION", 0, 0, 0, ""),
01018 Commands( "DISJOINT", 0, 0, 0, ""),
01019 Commands( "ELT", 0, 0, 0, ""),
01020 Commands( "ENCODE", 0, 0, 0, ""),
01021 Commands( "ENCRYPT", 0, 0, 0, ""),
01022 Commands( "ENDPOINT", 0, 0, 0, ""),
01023 Commands( "ENVELOPE", 0, 0, 0, ""),
01024 Commands( "EQUALS", 0, 0, 0, ""),
01025 Commands( "EXTERIORRING", 0, 0, 0, ""),
01026 Commands( "EXTRACT", 0, 0, 0, ""),
01027 Commands( "EXP", 0, 0, 0, ""),
01028 Commands( "EXPORT_SET", 0, 0, 0, ""),
01029 Commands( "FIELD", 0, 0, 0, ""),
01030 Commands( "FIND_IN_SET", 0, 0, 0, ""),
01031 Commands( "FLOOR", 0, 0, 0, ""),
01032 Commands( "FORMAT", 0, 0, 0, ""),
01033 Commands( "FOUND_ROWS", 0, 0, 0, ""),
01034 Commands( "FROM_DAYS", 0, 0, 0, ""),
01035 Commands( "FROM_UNIXTIME", 0, 0, 0, ""),
01036 Commands( "GET_LOCK", 0, 0, 0, ""),
01037 Commands( "GLENGTH", 0, 0, 0, ""),
01038 Commands( "GREATEST", 0, 0, 0, ""),
01039 Commands( "GROUP_CONCAT", 0, 0, 0, ""),
01040 Commands( "GROUP_UNIQUE_USERS", 0, 0, 0, ""),
01041 Commands( "HEX", 0, 0, 0, ""),
01042 Commands( "IFNULL", 0, 0, 0, ""),
01043 Commands( "INSTR", 0, 0, 0, ""),
01044 Commands( "INTERIORRINGN", 0, 0, 0, ""),
01045 Commands( "INTERSECTS", 0, 0, 0, ""),
01046 Commands( "ISCLOSED", 0, 0, 0, ""),
01047 Commands( "ISEMPTY", 0, 0, 0, ""),
01048 Commands( "ISNULL", 0, 0, 0, ""),
01049 Commands( "IS_FREE_LOCK", 0, 0, 0, ""),
01050 Commands( "IS_USED_LOCK", 0, 0, 0, ""),
01051 Commands( "LAST_INSERT_ID", 0, 0, 0, ""),
01052 Commands( "ISSIMPLE", 0, 0, 0, ""),
01053 Commands( "LAST_DAY", 0, 0, 0, ""),
01054 Commands( "LCASE", 0, 0, 0, ""),
01055 Commands( "LEAST", 0, 0, 0, ""),
01056 Commands( "LENGTH", 0, 0, 0, ""),
01057 Commands( "LN", 0, 0, 0, ""),
01058 Commands( "LOAD_FILE", 0, 0, 0, ""),
01059 Commands( "LOCATE", 0, 0, 0, ""),
01060 Commands( "LOG", 0, 0, 0, ""),
01061 Commands( "LOG2", 0, 0, 0, ""),
01062 Commands( "LOG10", 0, 0, 0, ""),
01063 Commands( "LOWER", 0, 0, 0, ""),
01064 Commands( "LPAD", 0, 0, 0, ""),
01065 Commands( "LTRIM", 0, 0, 0, ""),
01066 Commands( "MAKE_SET", 0, 0, 0, ""),
01067 Commands( "MAKEDATE", 0, 0, 0, ""),
01068 Commands( "MASTER_POS_WAIT", 0, 0, 0, ""),
01069 Commands( "MAX", 0, 0, 0, ""),
01070 Commands( "MBRCONTAINS", 0, 0, 0, ""),
01071 Commands( "MBRDISJOINT", 0, 0, 0, ""),
01072 Commands( "MBREQUAL", 0, 0, 0, ""),
01073 Commands( "MBRINTERSECTS", 0, 0, 0, ""),
01074 Commands( "MBROVERLAPS", 0, 0, 0, ""),
01075 Commands( "MBRTOUCHES", 0, 0, 0, ""),
01076 Commands( "MBRWITHIN", 0, 0, 0, ""),
01077 Commands( "MD5", 0, 0, 0, ""),
01078 Commands( "MID", 0, 0, 0, ""),
01079 Commands( "MIN", 0, 0, 0, ""),
01080 Commands( "MONTHNAME", 0, 0, 0, ""),
01081 Commands( "NAME_CONST", 0, 0, 0, ""),
01082 Commands( "NOW", 0, 0, 0, ""),
01083 Commands( "NULLIF", 0, 0, 0, ""),
01084 Commands( "NUMPOINTS", 0, 0, 0, ""),
01085 Commands( "OCTET_LENGTH", 0, 0, 0, ""),
01086 Commands( "OCT", 0, 0, 0, ""),
01087 Commands( "ORD", 0, 0, 0, ""),
01088 Commands( "OVERLAPS", 0, 0, 0, ""),
01089 Commands( "PERIOD_ADD", 0, 0, 0, ""),
01090 Commands( "PERIOD_DIFF", 0, 0, 0, ""),
01091 Commands( "PI", 0, 0, 0, ""),
01092 Commands( "POINTN", 0, 0, 0, ""),
01093 Commands( "POSITION", 0, 0, 0, ""),
01094 Commands( "POW", 0, 0, 0, ""),
01095 Commands( "POWER", 0, 0, 0, ""),
01096 Commands( "QUOTE", 0, 0, 0, ""),
01097 Commands( "RADIANS", 0, 0, 0, ""),
01098 Commands( "RAND", 0, 0, 0, ""),
01099 Commands( "RELEASE_LOCK", 0, 0, 0, ""),
01100 Commands( "REVERSE", 0, 0, 0, ""),
01101 Commands( "ROUND", 0, 0, 0, ""),
01102 Commands( "ROW_COUNT", 0, 0, 0, ""),
01103 Commands( "RPAD", 0, 0, 0, ""),
01104 Commands( "RTRIM", 0, 0, 0, ""),
01105 Commands( "SESSION_USER", 0, 0, 0, ""),
01106 Commands( "SUBDATE", 0, 0, 0, ""),
01107 Commands( "SIGN", 0, 0, 0, ""),
01108 Commands( "SIN", 0, 0, 0, ""),
01109 Commands( "SHA", 0, 0, 0, ""),
01110 Commands( "SHA1", 0, 0, 0, ""),
01111 Commands( "SLEEP", 0, 0, 0, ""),
01112 Commands( "SOUNDEX", 0, 0, 0, ""),
01113 Commands( "SPACE", 0, 0, 0, ""),
01114 Commands( "SQRT", 0, 0, 0, ""),
01115 Commands( "SRID", 0, 0, 0, ""),
01116 Commands( "STARTPOINT", 0, 0, 0, ""),
01117 Commands( "STD", 0, 0, 0, ""),
01118 Commands( "STDDEV", 0, 0, 0, ""),
01119 Commands( "STDDEV_POP", 0, 0, 0, ""),
01120 Commands( "STDDEV_SAMP", 0, 0, 0, ""),
01121 Commands( "STR_TO_DATE", 0, 0, 0, ""),
01122 Commands( "STRCMP", 0, 0, 0, ""),
01123 Commands( "SUBSTR", 0, 0, 0, ""),
01124 Commands( "SUBSTRING", 0, 0, 0, ""),
01125 Commands( "SUBSTRING_INDEX", 0, 0, 0, ""),
01126 Commands( "SUM", 0, 0, 0, ""),
01127 Commands( "SYSDATE", 0, 0, 0, ""),
01128 Commands( "SYSTEM_USER", 0, 0, 0, ""),
01129 Commands( "TAN", 0, 0, 0, ""),
01130 Commands( "TIME_FORMAT", 0, 0, 0, ""),
01131 Commands( "TO_DAYS", 0, 0, 0, ""),
01132 Commands( "TOUCHES", 0, 0, 0, ""),
01133 Commands( "TRIM", 0, 0, 0, ""),
01134 Commands( "UCASE", 0, 0, 0, ""),
01135 Commands( "UNCOMPRESS", 0, 0, 0, ""),
01136 Commands( "UNCOMPRESSED_LENGTH", 0, 0, 0, ""),
01137 Commands( "UNHEX", 0, 0, 0, ""),
01138 Commands( "UNIQUE_USERS", 0, 0, 0, ""),
01139 Commands( "UNIX_TIMESTAMP", 0, 0, 0, ""),
01140 Commands( "UPPER", 0, 0, 0, ""),
01141 Commands( "UUID", 0, 0, 0, ""),
01142 Commands( "VARIANCE", 0, 0, 0, ""),
01143 Commands( "VAR_POP", 0, 0, 0, ""),
01144 Commands( "VAR_SAMP", 0, 0, 0, ""),
01145 Commands( "VERSION", 0, 0, 0, ""),
01146 Commands( "WEEKDAY", 0, 0, 0, ""),
01147 Commands( "WEEKOFYEAR", 0, 0, 0, ""),
01148 Commands( "WITHIN", 0, 0, 0, ""),
01149 Commands( "X", 0, 0, 0, ""),
01150 Commands( "Y", 0, 0, 0, ""),
01151 Commands( "YEARWEEK", 0, 0, 0, ""),
01152
01153 Commands((char *)NULL, 0, 0, 0, "")
01154 };
01155
01156
01157 int history_length;
01158 static int not_in_history(const char *line);
01159 static void initialize_readline (char *name);
01160 static void fix_history(string *final_command);
01161
01162 static Commands *find_command(const char *name,char cmd_name);
01163 static bool add_line(string *buffer,char *line,char *in_string,
01164 bool *ml_comment);
01165 static void remove_cntrl(string *buffer);
01166 static void print_table_data(drizzle_result_st *result);
01167 static void print_tab_data(drizzle_result_st *result);
01168 static void print_table_data_vertically(drizzle_result_st *result);
01169 static void print_warnings(uint32_t error_code);
01170 static boost::posix_time::ptime start_timer(void);
01171 static void end_timer(boost::posix_time::ptime, string &buff);
01172 static void drizzle_end_timer(boost::posix_time::ptime, string &buff);
01173 static void nice_time(boost::posix_time::time_duration duration, string &buff);
01174 extern "C" void drizzle_end(int sig);
01175 extern "C" void handle_sigint(int sig);
01176 #if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
01177 static void window_resize(int sig);
01178 #endif
01179
01188 static bool server_shutdown(void)
01189 {
01190 drizzle_result_st result;
01191
01192 if (verbose)
01193 {
01194 printf(_("shutting down drizzled"));
01195 if (opt_drizzle_port > 0)
01196 {
01197 printf(_(" on port %d"), opt_drizzle_port);
01198 }
01199 printf("... ");
01200 }
01201
01202 drizzle_return_t ret;
01203 if (drizzle_shutdown(con, &result, DRIZZLE_SHUTDOWN_DEFAULT, &ret) == NULL or
01204 ret != DRIZZLE_RETURN_OK)
01205 {
01206 if (ret == DRIZZLE_RETURN_ERROR_CODE)
01207 {
01208 fprintf(stderr, _("shutdown failed; error: '%s'"), drizzle_result_error(&result));
01209 drizzle_result_free(&result);
01210 }
01211 else
01212 {
01213 fprintf(stderr, _("shutdown failed; error: '%s'"), drizzle_con_error(con));
01214 }
01215 return false;
01216 }
01217
01218 drizzle_result_free(&result);
01219
01220 if (verbose)
01221 {
01222 printf(_("done\n"));
01223 }
01224
01225 return true;
01226 }
01227
01228 static bool kill_query(uint32_t query_id)
01229 {
01230 drizzle_result_st result;
01231 drizzle_return_t ret;
01232
01233 if (verbose)
01234 {
01235 printf(_("killing query %u"), query_id);
01236 printf("... ");
01237 }
01238
01239 if (drizzle_kill(con, &result, query_id,
01240 &ret) == NULL || ret != DRIZZLE_RETURN_OK)
01241 {
01242 if (ret == DRIZZLE_RETURN_ERROR_CODE)
01243 {
01244 fprintf(stderr, _("kill failed; error: '%s'"),
01245 drizzle_result_error(&result));
01246 drizzle_result_free(&result);
01247 }
01248 else
01249 {
01250 fprintf(stderr, _("kill failed; error: '%s'"), drizzle_con_error(con));
01251 }
01252 return false;
01253 }
01254
01255 drizzle_result_free(&result);
01256
01257 if (verbose)
01258 printf(_("done\n"));
01259
01260 return true;
01261 }
01262
01271 static bool server_ping(void)
01272 {
01273 drizzle_result_st result;
01274 drizzle_return_t ret;
01275
01276 if (drizzle_ping(con, &result, &ret) != NULL && ret == DRIZZLE_RETURN_OK)
01277 {
01278 if (opt_silent < 2)
01279 printf(_("drizzled is alive\n"));
01280 }
01281 else
01282 {
01283 if (ret == DRIZZLE_RETURN_ERROR_CODE)
01284 {
01285 fprintf(stderr, _("ping failed; error: '%s'"),
01286 drizzle_result_error(&result));
01287 drizzle_result_free(&result);
01288 }
01289 else
01290 {
01291 fprintf(stderr, _("drizzled won't answer to ping, error: '%s'"), drizzle_con_error(con));
01292 }
01293 return false;
01294 }
01295 drizzle_result_free(&result);
01296 return true;
01297 }
01298
01313 static bool execute_commands(int *error)
01314 {
01315 bool executed= false;
01316 *error= 0;
01317
01318 if (opt_ping)
01319 {
01320 if (server_ping() == false)
01321 *error= 1;
01322 executed= true;
01323 }
01324
01325 if (opt_shutdown)
01326 {
01327 if (server_shutdown() == false)
01328 *error= 1;
01329 executed= true;
01330 }
01331
01332 if (opt_kill)
01333 {
01334 if (kill_query(opt_kill) == false)
01335 {
01336 *error= 1;
01337 }
01338 executed= true;
01339 }
01340
01341 return executed;
01342 }
01343
01344 static void check_timeout_value(uint32_t in_connect_timeout)
01345 {
01346 opt_connect_timeout= 0;
01347 if (in_connect_timeout > 3600*12)
01348 {
01349 cout << _("Error: Invalid Value for connect_timeout");
01350 exit(-1);
01351 }
01352 opt_connect_timeout= in_connect_timeout;
01353 }
01354
01355 static void check_max_input_line(uint32_t in_max_input_line)
01356 {
01357 opt_max_input_line= 0;
01358 if (in_max_input_line < 4096 || in_max_input_line > (int64_t)2*1024L*1024L*1024L)
01359 {
01360 cout << _("Error: Invalid Value for max_input_line");
01361 exit(-1);
01362 }
01363 opt_max_input_line= in_max_input_line - (in_max_input_line % 1024);
01364 }
01365
01366 int main(int argc,char *argv[])
01367 {
01368 try
01369 {
01370
01371 #if defined(ENABLE_NLS)
01372 # if defined(HAVE_LOCALE_H)
01373 setlocale(LC_ALL, "");
01374 # endif
01375 bindtextdomain("drizzle7", LOCALEDIR);
01376 textdomain("drizzle7");
01377 #endif
01378
01379 po::options_description commandline_options(_("Options used only in command line"));
01380 commandline_options.add_options()
01381 ("help,?",_("Displays this help and exit."))
01382 ("batch,B",_("Don't use history file. Disable interactive behavior. (Enables --silent)"))
01383 ("column-type-info", po::value<bool>(&column_types_flag)->default_value(false)->zero_tokens(),
01384 _("Display column type information."))
01385 ("comments,c", po::value<bool>(&preserve_comments)->default_value(false)->zero_tokens(),
01386 _("Preserve comments. Send comments to the server. The default is --skip-comments (discard comments), enable with --comments"))
01387 ("vertical,E", po::value<bool>(&vertical)->default_value(false)->zero_tokens(),
01388 _("Print the output of a query (rows) vertically."))
01389 ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
01390 _("Continue even if we get an sql error."))
01391 ("named-commands,G", po::value<bool>(&named_cmds)->default_value(false)->zero_tokens(),
01392 _("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."))
01393 ("no-beep,b", po::value<bool>(&opt_nobeep)->default_value(false)->zero_tokens(),
01394 _("Turn off beep on error."))
01395 ("disable-line-numbers", _("Do not write line numbers for errors."))
01396 ("disable-column-names", _("Do not write column names in results."))
01397 ("skip-column-names,N",
01398 _("Don't write column names in results. WARNING: -N is deprecated, use long version of this options instead."))
01399 ("set-variable,O", po::value<string>(),
01400 _("Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value."))
01401 ("table,t", po::value<bool>(&output_tables)->default_value(false)->zero_tokens(),
01402 _("Output in table format."))
01403 ("safe-updates,U", po::value<bool>(&safe_updates)->default_value(false)->zero_tokens(),
01404 _("Only allow UPDATE and DELETE that uses keys."))
01405 ("i-am-a-dummy,U", po::value<bool>(&safe_updates)->default_value(false)->zero_tokens(),
01406 _("Synonym for option --safe-updates, -U."))
01407 ("verbose,v", po::value<string>(&opt_verbose)->default_value(""),
01408 _("-v vvv implies that verbose= 3, Used to specify verbose"))
01409 ("version,V", _("Output version information and exit."))
01410 ("secure-auth", po::value<bool>(&opt_secure_auth)->default_value(false)->zero_tokens(),
01411 _("Refuse client connecting to server if it uses old (pre-4.1.1) protocol"))
01412 ("show-warnings", po::value<bool>(&show_warnings)->default_value(false)->zero_tokens(),
01413 _("Show warnings after every statement."))
01414 ("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(0),
01415 _("Number of lines before each import progress report."))
01416 ("ping", po::value<bool>(&opt_ping)->default_value(false)->zero_tokens(),
01417 _("Ping the server to check if it's alive."))
01418 ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
01419 _("Configuration file defaults are not used if no-defaults is set"))
01420 ;
01421
01422 po::options_description drizzle_options(_("Options specific to the drizzle client"));
01423 drizzle_options.add_options()
01424 ("disable-auto-rehash,A",
01425 _("Disable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time."))
01426 ("auto-vertical-output", po::value<bool>(&auto_vertical_output)->default_value(false)->zero_tokens(),
01427 _("Automatically switch to vertical output mode if the result is wider than the terminal width."))
01428 ("database,D", po::value<string>(¤t_db)->default_value(""),
01429 _("Database to use."))
01430 ("default-character-set",po::value<string>(),
01431 _("(not used)"))
01432 ("delimiter", po::value<string>(&delimiter_str)->default_value(";"),
01433 _("Delimiter to be used."))
01434 ("execute,e", po::value<string>(),
01435 _("Execute command and quit. (Disables --force and history file)"))
01436 ("local-infile", po::value<bool>(&opt_local_infile)->default_value(false)->zero_tokens(),
01437 _("Enable LOAD DATA LOCAL INFILE."))
01438 ("unbuffered,n", po::value<bool>(&unbuffered)->default_value(false)->zero_tokens(),
01439 _("Flush buffer after each query."))
01440 ("sigint-ignore", po::value<bool>(&opt_sigint_ignore)->default_value(false)->zero_tokens(),
01441 _("Ignore SIGINT (CTRL-C)"))
01442 ("one-database,o", po::value<bool>(&one_database)->default_value(false)->zero_tokens(),
01443 _("Only update the default database. This is useful for skipping updates to other database in the update log."))
01444 ("pager", po::value<string>(),
01445 _("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."))
01446 ("disable-pager", po::value<bool>(&opt_nopager)->default_value(false)->zero_tokens(),
01447 _("Disable pager and print to stdout. See interactive help (\\h) also."))
01448 ("prompt", po::value<string>(¤t_prompt)->default_value(""),
01449 _("Set the drizzle prompt to this value."))
01450 ("quick,q", po::value<bool>(&quick)->default_value(false)->zero_tokens(),
01451 _("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."))
01452 ("raw,r", po::value<bool>(&opt_raw_data)->default_value(false)->zero_tokens(),
01453 _("Write fields without conversion. Used with --batch."))
01454 ("disable-reconnect", _("Do not reconnect if the connection is lost."))
01455 ("shutdown", po::value<bool>()->zero_tokens(),
01456 _("Shutdown the server"))
01457 ("silent,s", _("Be more silent. Print results with a tab as separator, each row on new line."))
01458 ("kill", po::value<uint32_t>(&opt_kill)->default_value(0),
01459 _("Kill a running query."))
01460 ("tee", po::value<string>(),
01461 _("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."))
01462 ("disable-tee", po::value<bool>()->default_value(false)->zero_tokens(),
01463 _("Disable outfile. See interactive help (\\h) also."))
01464 ("connect-timeout", po::value<uint32_t>(&opt_connect_timeout)->default_value(0)->notifier(&check_timeout_value),
01465 _("Number of seconds before connection timeout."))
01466 ("max-input-line", po::value<uint32_t>(&opt_max_input_line)->default_value(16*1024L*1024L)->notifier(&check_max_input_line),
01467 _("Max length of input line"))
01468 ("select-limit", po::value<uint32_t>(&select_limit)->default_value(1000L),
01469 _("Automatic limit for SELECT when using --safe-updates"))
01470 ("max-join-size", po::value<uint32_t>(&max_join_size)->default_value(1000000L),
01471 _("Automatic limit for rows in a join when using --safe-updates"))
01472 ;
01473
01474 po::options_description client_options(_("Options specific to the client"));
01475 client_options.add_options()
01476 ("host,h", po::value<string>(¤t_host)->default_value("localhost"),
01477 _("Connect to host"))
01478 ("password,P", po::value<string>(¤t_password)->default_value(PASSWORD_SENTINEL),
01479 _("Password to use when connecting to server. If password is not given it's asked from the tty."))
01480 ("port,p", po::value<uint32_t>()->default_value(0),
01481 _("Port number to use for connection or 0 for default to, in order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, built-in default"))
01482 ("user,u", po::value<string>(¤t_user)->default_value(UserDetect().getUser()),
01483 _("User for login if not current user."))
01484 ("protocol",po::value<string>(&opt_protocol)->default_value("mysql"),
01485 _("The protocol of connection (mysql, mysql-plugin-auth, or drizzle)."))
01486 ;
01487 po::options_description long_options(_("Allowed Options"));
01488 long_options.add(commandline_options).add(drizzle_options).add(client_options);
01489
01490 std::string system_config_dir_drizzle(SYSCONFDIR);
01491 system_config_dir_drizzle.append("/drizzle/drizzle.cnf");
01492
01493 std::string system_config_dir_client(SYSCONFDIR);
01494 system_config_dir_client.append("/drizzle/client.cnf");
01495
01496 std::string user_config_dir((getenv("XDG_CONFIG_HOME")? getenv("XDG_CONFIG_HOME"):"~/.config"));
01497
01498 if (user_config_dir.compare(0, 2, "~/") == 0)
01499 {
01500 char *homedir;
01501 homedir= getenv("HOME");
01502 if (homedir != NULL)
01503 user_config_dir.replace(0, 1, homedir);
01504 }
01505
01506 po::variables_map vm;
01507
01508 po::positional_options_description p;
01509 p.add("database", 1);
01510
01511
01512 int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
01513
01514 po::store(po::command_line_parser(argc, argv).options(long_options).
01515 style(style).positional(p).extra_parser(parse_password_arg).run(),
01516 vm);
01517
01518 if (! vm["no-defaults"].as<bool>())
01519 {
01520 std::string user_config_dir_drizzle(user_config_dir);
01521 user_config_dir_drizzle.append("/drizzle/drizzle.cnf");
01522
01523 std::string user_config_dir_client(user_config_dir);
01524 user_config_dir_client.append("/drizzle/client.cnf");
01525
01526 ifstream user_drizzle_ifs(user_config_dir_drizzle.c_str());
01527 po::store(dpo::parse_config_file(user_drizzle_ifs, drizzle_options), vm);
01528
01529 ifstream user_client_ifs(user_config_dir_client.c_str());
01530 po::store(dpo::parse_config_file(user_client_ifs, client_options), vm);
01531
01532 ifstream system_drizzle_ifs(system_config_dir_drizzle.c_str());
01533 store(dpo::parse_config_file(system_drizzle_ifs, drizzle_options), vm);
01534
01535 ifstream system_client_ifs(system_config_dir_client.c_str());
01536 po::store(dpo::parse_config_file(system_client_ifs, client_options), vm);
01537 }
01538
01539 po::notify(vm);
01540
01541 default_prompt= strdup(getenv("DRIZZLE_PS1") ?
01542 getenv("DRIZZLE_PS1") :
01543 "drizzle> ");
01544 if (default_prompt == NULL)
01545 {
01546 fprintf(stderr, _("Memory allocation error while constructing initial "
01547 "prompt. Aborting.\n"));
01548 exit(ENOMEM);
01549 }
01550
01551 if (current_prompt.empty())
01552 current_prompt= strdup(default_prompt);
01553
01554 if (current_prompt.empty())
01555 {
01556 fprintf(stderr, _("Memory allocation error while constructing initial "
01557 "prompt. Aborting.\n"));
01558 exit(ENOMEM);
01559 }
01560 processed_prompt= new string();
01561 processed_prompt->reserve(32);
01562
01563 prompt_counter=0;
01564
01565 outfile.clear();
01566 pager= "stdout";
01567 if (const char* tmp= getenv("PAGER"))
01568 {
01569 if (*tmp)
01570 {
01571 default_pager_set= 1;
01572 default_pager= tmp;
01573 }
01574 }
01575 if (not isatty(0) || not isatty(1))
01576 {
01577 status.setBatch(1);
01578 opt_silent= 1;
01579 }
01580 else
01581 status.setAddToHistory(1);
01582 status.setExitStatus(1);
01583
01584 {
01585
01586
01587
01588
01589
01590 int stdout_fileno_copy;
01591 stdout_fileno_copy= dup(fileno(stdout));
01592 if (stdout_fileno_copy == -1)
01593 fclose(stdout);
01594 else
01595 close(stdout_fileno_copy);
01596 }
01597
01598
01599
01600 line_numbers= not vm.count("disable-line-numbers");
01601 column_names= not vm.count("disable-column-names");
01602 opt_rehash= not vm.count("disable-auto-rehash");
01603 opt_reconnect= not vm.count("disable-reconnect");
01604
01605
01606 if (vm.count("shutdown"))
01607 {
01608 opt_rehash= false;
01609 opt_shutdown= true;
01610 }
01611
01612 if (vm.count("delimiter"))
01613 {
01614
01615 if (! strstr(delimiter_str.c_str(), "\\"))
01616 {
01617 delimiter= delimiter_str.c_str();
01618 }
01619 else
01620 {
01621 put_info(_("DELIMITER cannot contain a backslash character"),
01622 INFO_ERROR,0,0);
01623 exit(-1);
01624 }
01625
01626 delimiter_length= (uint32_t)strlen(delimiter);
01627 }
01628 if (vm.count("tee"))
01629 {
01630 if (vm["tee"].as<string>().empty())
01631 {
01632 if (opt_outfile)
01633 end_tee();
01634 }
01635 else
01636 init_tee(vm["tee"].as<string>().c_str());
01637 }
01638 if (vm["disable-tee"].as<bool>())
01639 {
01640 if (opt_outfile)
01641 end_tee();
01642 }
01643 if (vm.count("pager"))
01644 {
01645 if (vm["pager"].as<string>().empty())
01646 opt_nopager= 1;
01647 else
01648 {
01649 opt_nopager= 0;
01650 if (vm[pager].as<string>().length())
01651 {
01652 default_pager_set= 1;
01653 pager= vm["pager"].as<string>();
01654 default_pager= pager;
01655 }
01656 else if (default_pager_set)
01657 pager= default_pager;
01658 else
01659 opt_nopager= 1;
01660 }
01661 }
01662 if (vm.count("disable-pager"))
01663 {
01664 opt_nopager= 1;
01665 }
01666
01667 if (vm.count("no-auto-rehash"))
01668 opt_rehash= 0;
01669
01670 if (vm.count("skip-column-names"))
01671 column_names= 0;
01672
01673 if (vm.count("execute"))
01674 {
01675 status.setBatch(1);
01676 status.setAddToHistory(1);
01677 if (status.getLineBuff() == NULL)
01678 status.setLineBuff(opt_max_input_line,NULL);
01679 if (status.getLineBuff() == NULL)
01680 {
01681 exit(1);
01682 }
01683 status.getLineBuff()->addString(vm["execute"].as<string>().c_str());
01684 }
01685
01686 if (one_database)
01687 skip_updates= true;
01688
01689 if (vm.count("protocol"))
01690 {
01691 boost::to_lower(opt_protocol);
01692 if (not opt_protocol.compare("mysql"))
01693 {
01694 global_con_options= (drizzle_con_options_t)(DRIZZLE_CON_MYSQL|DRIZZLE_CON_INTERACTIVE);
01695 use_drizzle_protocol= false;
01696 }
01697 else if (not opt_protocol.compare("mysql-plugin-auth"))
01698 {
01699 global_con_options= (drizzle_con_options_t)(DRIZZLE_CON_MYSQL|DRIZZLE_CON_INTERACTIVE|DRIZZLE_CON_AUTH_PLUGIN);
01700 use_drizzle_protocol= false;
01701 }
01702 else if (not opt_protocol.compare("drizzle"))
01703 {
01704 global_con_options= (drizzle_con_options_t)(DRIZZLE_CON_EXPERIMENTAL);
01705 use_drizzle_protocol= true;
01706 }
01707 else
01708 {
01709 cout << _("Error: Unknown protocol") << " '" << opt_protocol << "'" << endl;
01710 exit(-1);
01711 }
01712 }
01713
01714 if (vm.count("port"))
01715 {
01716 opt_drizzle_port= vm["port"].as<uint32_t>();
01717
01718
01719
01720
01721 if (opt_drizzle_port > 65535)
01722 {
01723 printf(_("Error: Value of %" PRIu32 " supplied for port is not valid.\n"), opt_drizzle_port);
01724 exit(-1);
01725 }
01726 }
01727
01728 if (vm.count("password"))
01729 {
01730 if (!opt_password.empty())
01731 opt_password.erase();
01732 if (current_password == PASSWORD_SENTINEL)
01733 {
01734 opt_password= "";
01735 }
01736 else
01737 {
01738 opt_password= current_password;
01739 tty_password= false;
01740 }
01741 }
01742 else
01743 {
01744 tty_password= true;
01745 }
01746
01747
01748 if (!opt_verbose.empty())
01749 {
01750 verbose= opt_verbose.length();
01751 }
01752
01753 if (vm.count("batch"))
01754 {
01755 status.setBatch(1);
01756 status.setAddToHistory(0);
01757 if (opt_silent < 1)
01758 {
01759 opt_silent= 1;
01760 }
01761 }
01762 if (vm.count("silent"))
01763 {
01764 opt_silent= 2;
01765 }
01766
01767 if (vm.count("help") || vm.count("version"))
01768 {
01769 printf(_("Drizzle client %s build %s, for %s-%s (%s) using readline %s\n"),
01770 drizzle_version(), VERSION,
01771 HOST_VENDOR, HOST_OS, HOST_CPU,
01772 rl_library_version);
01773 if (vm.count("version"))
01774 exit(0);
01775 printf(_("Copyright (C) 2008 Sun Microsystems\n"
01776 "This software comes with ABSOLUTELY NO WARRANTY. "
01777 "This is free software,\n"
01778 "and you are welcome to modify and redistribute it "
01779 "under the GPL license\n"));
01780 printf(_("Usage: drizzle [OPTIONS] [schema]\n"));
01781 cout << long_options;
01782 exit(0);
01783 }
01784
01785
01786 if (process_options())
01787 {
01788 exit(1);
01789 }
01790
01791 memset(&drizzle, 0, sizeof(drizzle));
01792 if (sql_connect(current_host, current_db, current_user, opt_password))
01793 {
01794 quick= 1;
01795 status.setExitStatus(1);
01796 drizzle_end(-1);
01797 }
01798
01799 int command_error;
01800 if (execute_commands(&command_error) != false)
01801 {
01802
01803 exit(command_error);
01804 }
01805
01806 if (status.getBatch() && !status.getLineBuff())
01807 {
01808 status.setLineBuff(opt_max_input_line, stdin);
01809 if (status.getLineBuff() == NULL)
01810 {
01811 exit(1);
01812 }
01813 }
01814
01815 if (!status.getBatch())
01816 ignore_errors=1;
01817
01818 if (opt_sigint_ignore)
01819 signal(SIGINT, SIG_IGN);
01820 else
01821 signal(SIGINT, handle_sigint);
01822 signal(SIGQUIT, drizzle_end);
01823
01824 #if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
01825
01826 signal(SIGWINCH, window_resize);
01827
01828 window_resize(0);
01829 #endif
01830 std::vector<char> output_buff;
01831 output_buff.resize(512);
01832
01833 snprintf(&output_buff[0], output_buff.size(),
01834 _("Welcome to the Drizzle client.. Commands end with %s or \\g."),
01835 delimiter);
01836
01837 put_info(&output_buff[0], INFO_INFO, 0, 0);
01838
01839 glob_buffer= new string();
01840 glob_buffer->reserve(512);
01841
01842 snprintf(&output_buff[0], output_buff.size(),
01843 _("Your Drizzle connection id is %u\nConnection protocol: %s\nServer version: %s\n"),
01844 drizzle_con_thread_id(con),
01845 opt_protocol.c_str(),
01846 server_version_string(con));
01847 put_info(&output_buff[0], INFO_INFO, 0, 0);
01848
01849
01850 initialize_readline((char *)current_prompt.c_str());
01851 if (!status.getBatch() && !quick)
01852 {
01853
01854 if (getenv("DRIZZLE_HISTFILE"))
01855 histfile= strdup(getenv("DRIZZLE_HISTFILE"));
01856 else if (getenv("HOME"))
01857 {
01858 histfile=(char*) malloc(strlen(getenv("HOME")) + strlen("/.drizzle_history") + 2);
01859 if (histfile)
01860 sprintf(histfile,"%s/.drizzle_history",getenv("HOME"));
01861 char link_name[FN_REFLEN];
01862 ssize_t sym_link_size= readlink(histfile,link_name,FN_REFLEN-1);
01863 if (sym_link_size >= 0)
01864 {
01865 link_name[sym_link_size]= '\0';
01866 if (strncmp(link_name, "/dev/null", 10) == 0)
01867 {
01868
01869 free(histfile);
01870 histfile= 0;
01871 }
01872 }
01873 }
01874 if (histfile)
01875 {
01876 if (verbose)
01877 tee_fprintf(stdout, _("Reading history-file %s\n"),histfile);
01878 read_history(histfile);
01879 histfile_tmp= (char*) malloc((uint32_t) strlen(histfile) + 5);
01880 sprintf(histfile_tmp, "%s.TMP", histfile);
01881 }
01882 }
01883
01884 put_info(_("Type 'help;' or '\\h' for help. "
01885 "Type '\\c' to clear the buffer.\n"),INFO_INFO,0,0);
01886 status.setExitStatus(read_and_execute(!status.getBatch()));
01887 if (opt_outfile)
01888 end_tee();
01889 drizzle_end(0);
01890 }
01891
01892 catch(exception &err)
01893 {
01894 cerr << _("Error:") << err.what() << endl;
01895 }
01896 return(0);
01897 }
01898
01899 void drizzle_end(int sig)
01900 {
01901 drizzle_con_free(con);
01902 drizzle_free(drizzle);
01903 if (!status.getBatch() && !quick && histfile)
01904 {
01905
01906 if (verbose)
01907 tee_fprintf(stdout, _("Writing history-file %s\n"),histfile);
01908 if (!write_history(histfile_tmp))
01909 rename(histfile_tmp, histfile);
01910 }
01911 delete status.getLineBuff();
01912 status.setLineBuff(0);
01913
01914 if (sig >= 0)
01915 put_info(sig ? _("Aborted") : _("Bye"), INFO_RESULT,0,0);
01916 delete glob_buffer;
01917 delete processed_prompt;
01918 opt_password.erase();
01919 free(histfile);
01920 free(histfile_tmp);
01921 current_db.erase();
01922 current_host.erase();
01923 current_user.erase();
01924 free(full_username);
01925 free(part_username);
01926 free(default_prompt);
01927 current_prompt.erase();
01928 exit(status.getExitStatus());
01929 }
01930
01931
01932
01933
01934
01935
01936
01937 extern "C"
01938 void handle_sigint(int sig)
01939 {
01940
01941 if (executing_query == false or interrupted_query)
01942 { }
01943 else if (drizzle)
01944 {
01945 drizzle_con_st *kill_drizzle_con;
01946 if ((kill_drizzle_con= drizzle_con_add_tcp(drizzle,
01947 current_host.c_str(), opt_drizzle_port,
01948 current_user.c_str(), opt_password.c_str(), NULL,
01949 use_drizzle_protocol ? DRIZZLE_CON_EXPERIMENTAL : DRIZZLE_CON_MYSQL)))
01950 {
01951
01952 char kill_buffer[40];
01953 snprintf(kill_buffer, sizeof(kill_buffer), "KILL /*!50000 QUERY */ %u", drizzle_con_thread_id(kill_drizzle_con));
01954
01955 drizzle_return_t ret;
01956 drizzle_result_st res;
01957 if ((drizzle_query_str(kill_drizzle_con, &res, kill_buffer, &ret)))
01958 {
01959 drizzle_result_free(&res);
01960 }
01961
01962 drizzle_con_free(kill_drizzle_con);
01963
01964 tee_fprintf(stdout, _("Query aborted by Ctrl+C\n"));
01965
01966 interrupted_query= true;
01967
01968 return;
01969 }
01970 }
01971
01972 drizzle_end(sig);
01973 }
01974
01975
01976 #if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
01977 void window_resize(int)
01978 {
01979 struct winsize window_size;
01980
01981 if (ioctl(fileno(stdin), TIOCGWINSZ, &window_size) == 0)
01982 terminal_width= window_size.ws_col;
01983 }
01984 #endif
01985
01986
01987
01988 static int process_options()
01989 {
01990 if (const char* tmp= getenv("DRIZZLE_HOST"))
01991 current_host= tmp;
01992
01993 if (const char* pagpoint= getenv("PAGER"))
01994 {
01995 pager= pagpoint;
01996 }
01997 else
01998 {
01999 pager= "stdout";
02000 opt_nopager= 1;
02001 }
02002 default_pager= pager;
02003
02004
02005
02006 if (status.getBatch())
02007 {
02008 default_pager= "stdout";
02009 pager= "stdout";
02010 opt_nopager= 1;
02011 default_pager_set= 0;
02012 opt_outfile= 0;
02013 opt_reconnect= 0;
02014 }
02015
02016 if (tty_password)
02017 opt_password= client_get_tty_password(NULL);
02018 return(0);
02019 }
02020
02021 static int read_and_execute(bool interactive)
02022 {
02023 char *line;
02024 char in_string=0;
02025 uint32_t line_number=0;
02026 bool ml_comment= 0;
02027 Commands *com;
02028 status.setExitStatus(1);
02029
02030 for (;;)
02031 {
02032 if (!interactive)
02033 {
02034 if (status.getLineBuff())
02035 line= status.getLineBuff()->readline();
02036 else
02037 line= 0;
02038
02039 line_number++;
02040 if (show_progress_size > 0)
02041 {
02042 if ((line_number % show_progress_size) == 0)
02043 fprintf(stderr, _("Processing line: %"PRIu32"\n"), line_number);
02044 }
02045 if (!glob_buffer->empty())
02046 status.setQueryStartLine(line_number);
02047 }
02048 else
02049 {
02050 string prompt(ml_comment
02051 ? " /*> "
02052 : glob_buffer->empty()
02053 ? construct_prompt()
02054 : not in_string
02055 ? " -> "
02056 : in_string == '\''
02057 ? " '> "
02058 : in_string == '`'
02059 ? " `> "
02060 : " \"> ");
02061 if (opt_outfile && glob_buffer->empty())
02062 fflush(OUTFILE);
02063
02064 if (opt_outfile)
02065 fputs(prompt.c_str(), OUTFILE);
02066 line= readline(prompt.c_str());
02067
02068
02069
02070
02071 if (opt_outfile && line)
02072 fprintf(OUTFILE, "%s\n", line);
02073 }
02074
02075 if (!line)
02076 {
02077 status.setExitStatus(0);
02078 break;
02079 }
02080
02081
02082
02083
02084
02085 if ((named_cmds || (glob_buffer->empty()))
02086 && !ml_comment && !in_string && (com=find_command(line,0)))
02087 {
02088 if ((*com->func)(glob_buffer,line) > 0)
02089 break;
02090
02091 if (glob_buffer->empty())
02092 in_string=0;
02093 if (interactive && status.getAddToHistory() && not_in_history(line))
02094 add_history(line);
02095 continue;
02096 }
02097 if (add_line(glob_buffer,line,&in_string,&ml_comment))
02098 break;
02099 }
02100
02101
02102 if (!interactive && !status.getExitStatus())
02103 {
02104 remove_cntrl(glob_buffer);
02105 if (!glob_buffer->empty())
02106 {
02107 status.setExitStatus(1);
02108 if (com_go(glob_buffer,line) <= 0)
02109 status.setExitStatus(0);
02110 }
02111 }
02112
02113 return status.getExitStatus();
02114 }
02115
02116
02117 static Commands *find_command(const char *name,char cmd_char)
02118 {
02119 uint32_t len;
02120 const char *end;
02121
02122 if (!name)
02123 {
02124 len=0;
02125 end=0;
02126 }
02127 else
02128 {
02129 while (isspace(*name))
02130 name++;
02131
02132
02133
02134
02135
02136 if (strstr(name, "\\g") || (strstr(name, delimiter) &&
02137 !(strlen(name) >= 9 &&
02138 !strcmp(name, "delimiter"))))
02139 return(NULL);
02140 if ((end=strcont(name," \t")))
02141 {
02142 len=(uint32_t) (end - name);
02143 while (isspace(*end))
02144 end++;
02145 if (!*end)
02146 end=0;
02147 }
02148 else
02149 len=(uint32_t) strlen(name);
02150 }
02151
02152 for (uint32_t i= 0; commands[i].getName(); i++)
02153 {
02154 if (commands[i].func &&
02155 ((name && !strncmp(name, commands[i].getName(), len)
02156 && !commands[i].getName()[len] && (!end || (end && commands[i].getTakesParams()))) || (!name && commands[i].getCmdChar() == cmd_char)))
02157 {
02158 return(&commands[i]);
02159 }
02160 }
02161 return(NULL);
02162 }
02163
02164
02165 static bool add_line(string *buffer, char *line, char *in_string,
02166 bool *ml_comment)
02167 {
02168 unsigned char inchar;
02169 char *pos, *out;
02170 Commands *com;
02171 bool need_space= 0;
02172 bool ss_comment= 0;
02173
02174
02175 if (!line[0] && (buffer->empty()))
02176 return(0);
02177 if (status.getAddToHistory() && line[0] && not_in_history(line))
02178 add_history(line);
02179
02180 for (pos=out=line ; (inchar= (unsigned char) *pos) ; pos++)
02181 {
02182 if (!preserve_comments)
02183 {
02184
02185 if (isspace(inchar) && (out == line) &&
02186 (buffer->empty()))
02187 continue;
02188 }
02189
02190
02191 if (not drizzled::utf8::is_single(*pos))
02192 {
02193 int length;
02194 if ((length= drizzled::utf8::sequence_length(*pos)))
02195 {
02196 if (!*ml_comment || preserve_comments)
02197 {
02198 while (length--)
02199 *out++ = *pos++;
02200 pos--;
02201 }
02202 else
02203 pos+= length - 1;
02204 continue;
02205 }
02206 }
02207 if (!*ml_comment && inchar == '\\' &&
02208 !(*in_string && (drizzle_con_status(con) & DRIZZLE_CON_STATUS_NO_BACKSLASH_ESCAPES)))
02209 {
02210
02211
02212 if (!(inchar = (unsigned char) *++pos))
02213 break;
02214 if (*in_string || inchar == 'N')
02215 {
02216 *out++='\\';
02217 *out++= (char) inchar;
02218 continue;
02219 }
02220 if ((com=find_command(NULL,(char) inchar)))
02221 {
02222
02223 if (out != line)
02224 {
02225 buffer->append(line, (out-line));
02226 out= line;
02227 }
02228
02229 if ((*com->func)(buffer,pos-1) > 0)
02230 return(1);
02231 if (com->getTakesParams())
02232 {
02233 if (ss_comment)
02234 {
02235
02236
02237
02238
02239
02240 for (pos++; *pos && (*pos != '*' || *(pos + 1) != '/'); pos++)
02241 ;
02242 pos--;
02243 }
02244 else
02245 {
02246 for (pos++ ;
02247 *pos && (*pos != *delimiter ||
02248 strncmp(pos + 1, delimiter + 1,
02249 strlen(delimiter + 1))) ; pos++)
02250 ;
02251 if (!*pos)
02252 pos--;
02253 else
02254 pos+= delimiter_length - 1;
02255 }
02256 }
02257 }
02258 else
02259 {
02260 string buff(_("Unknown command: "));
02261 buff.push_back('\'');
02262 buff.push_back(inchar);
02263 buff.push_back('\'');
02264 buff.push_back('.');
02265 if (put_info(buff.c_str(),INFO_ERROR,0,0) > 0)
02266 return(1);
02267 *out++='\\';
02268 *out++=(char) inchar;
02269 continue;
02270 }
02271 }
02272 else if (!*ml_comment && !*in_string && !strncmp(pos, delimiter,
02273 strlen(delimiter)))
02274 {
02275
02276 pos+= delimiter_length;
02277
02278 if (preserve_comments)
02279 {
02280 while (isspace(*pos))
02281 *out++= *pos++;
02282 }
02283
02284 if (out != line)
02285 {
02286 buffer->append(line, (out-line));
02287 out= line;
02288 }
02289
02290 if (preserve_comments && ((*pos == '#') ||
02291 ((*pos == '-') &&
02292 (pos[1] == '-') &&
02293 isspace(pos[2]))))
02294 {
02295
02296 buffer->append(pos);
02297 pos+= strlen(pos);
02298 }
02299
02300 pos--;
02301
02302 if ((com= find_command(buffer->c_str(), 0)))
02303 {
02304
02305 if ((*com->func)(buffer, buffer->c_str()) > 0)
02306 return(1);
02307 }
02308 else
02309 {
02310 if (com_go(buffer, 0) > 0)
02311 return(1);
02312 }
02313 buffer->clear();
02314 }
02315 else if (!*ml_comment
02316 && (!*in_string
02317 && (inchar == '#'
02318 || (inchar == '-'
02319 && pos[1] == '-'
02320 && isspace(pos[2])))))
02321 {
02322
02323 if (out != line)
02324 {
02325 buffer->append(line, (out - line));
02326 out= line;
02327 }
02328
02329
02330 if (preserve_comments)
02331 {
02332 bool started_with_nothing= !buffer->empty();
02333 buffer->append(pos);
02334
02335
02336
02337
02338
02339
02340 if (started_with_nothing)
02341 {
02342 if (com_go(buffer, 0) > 0)
02343 return 1;
02344 buffer->clear();
02345 }
02346 }
02347
02348 break;
02349 }
02350 else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
02351 *(pos+2) != '!')
02352 {
02353 if (preserve_comments)
02354 {
02355 *out++= *pos++;
02356 *out++= *pos;
02357 }
02358 else
02359 pos++;
02360 *ml_comment= 1;
02361 if (out != line)
02362 {
02363 buffer->append(line, (out-line));
02364 out=line;
02365 }
02366 }
02367 else if (*ml_comment && !ss_comment && inchar == '*' && *(pos + 1) == '/')
02368 {
02369 if (preserve_comments)
02370 {
02371 *out++= *pos++;
02372 *out++= *pos;
02373 }
02374 else
02375 pos++;
02376 *ml_comment= 0;
02377 if (out != line)
02378 {
02379 buffer->append(line, (out - line));
02380 out= line;
02381 }
02382
02383
02384 need_space= 1;
02385 }
02386 else
02387 {
02388
02389 if (!*in_string && inchar == '/' && *(pos + 1) == '*' &&
02390 *(pos + 2) == '!')
02391 ss_comment= 1;
02392 else if (!*in_string && ss_comment && inchar == '*' && *(pos + 1) == '/')
02393 ss_comment= 0;
02394 if (inchar == *in_string)
02395 *in_string= 0;
02396 else if (!*ml_comment && !*in_string &&
02397 (inchar == '\'' || inchar == '"' || inchar == '`'))
02398 *in_string= (char) inchar;
02399 if (!*ml_comment || preserve_comments)
02400 {
02401 if (need_space && !isspace((char)inchar))
02402 *out++= ' ';
02403 need_space= 0;
02404 *out++= (char) inchar;
02405 }
02406 }
02407 }
02408 if (out != line || (buffer->length() > 0))
02409 {
02410 *out++='\n';
02411 uint32_t length=(uint32_t) (out-line);
02412 if ((buffer->length() + length) > opt_max_input_line)
02413 {
02414 status.setExitStatus(1);
02415 put_info(_("Not found a delimiter within max_input_line of input"), INFO_ERROR, 0, 0);
02416 return 1;
02417 }
02418 if ((!*ml_comment || preserve_comments))
02419 buffer->append(line, length);
02420 }
02421 return(0);
02422 }
02423
02424
02425
02426
02427
02428
02429 static char **mysql_completion (const char *text, int start, int end);
02430 extern "C" char *new_command_generator(const char *text, int);
02431
02432
02433
02434
02435
02436
02437 static char *no_completion(const char *, int)
02438 {
02439
02440 return 0;
02441 }
02442
02443
02444
02445 static void fix_history(string *final_command)
02446 {
02447 int total_lines = 1;
02448 const char *ptr = final_command->c_str();
02449 char str_char = '\0';
02450
02451
02452 string fixed_buffer;
02453 fixed_buffer.reserve(512);
02454
02455
02456 while (*ptr != '\0')
02457 {
02458 switch (*ptr) {
02459
02460 case '"':
02461 case '\'':
02462 case '`':
02463
02464 if (str_char == '\0')
02465 str_char = *ptr;
02466 else if (str_char == *ptr)
02467 str_char = '\0';
02468 fixed_buffer.append(ptr, 1);
02469 break;
02470 case '\n':
02471
02472
02473
02474
02475 fixed_buffer.append((str_char == '\0') ? " " : "\n");
02476 total_lines++;
02477 break;
02478 case '\\':
02479 fixed_buffer.append("\\");
02480
02481 if (str_char)
02482 {
02483 ptr++;
02484
02485 if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
02486 fixed_buffer.append(ptr, 1);
02487 else
02488 ptr--;
02489 }
02490 break;
02491 default:
02492 fixed_buffer.append(ptr, 1);
02493 }
02494 ptr++;
02495 }
02496 if (total_lines > 1)
02497 add_history(fixed_buffer.c_str());
02498 }
02499
02500
02501
02502
02503
02504 static int not_in_history(const char *line)
02505 {
02506 HIST_ENTRY *oldhist = history_get(history_length);
02507
02508 if (oldhist == 0)
02509 return 1;
02510 if (strcmp(oldhist->line,line) == 0)
02511 return 0;
02512 return 1;
02513 }
02514
02515 static void initialize_readline (char *name)
02516 {
02517
02518 rl_readline_name= name;
02519
02520
02521 rl_attempted_completion_function= (rl_completion_func_t*)&mysql_completion;
02522 rl_completion_entry_function= (drizzle_compentry_func_t*)&no_completion;
02523 }
02524
02525
02526
02527
02528
02529
02530
02531
02532 char **mysql_completion (const char *text, int, int)
02533 {
02534 if (!status.getBatch() && !quick)
02535 return rl_completion_matches(text, new_command_generator);
02536 else
02537 return (char**) 0;
02538 }
02539
02540 inline string lower_string(const string& from)
02541 {
02542 return boost::to_lower_copy(from);
02543 }
02544
02545 inline string lower_string(const char* from)
02546 {
02547 return boost::to_lower_copy(string(from));
02548 }
02549
02550 template <class T>
02551 class CompletionMatch :
02552 public unary_function<const string&, bool>
02553 {
02554 string match_text;
02555 T match_func;
02556 public:
02557 CompletionMatch(string text) : match_text(text) {}
02558 inline bool operator() (const pair<string,string> &match_against) const
02559 {
02560 string sub_match= lower_string(match_against.first.substr(0,match_text.size()));
02561 return match_func(sub_match,match_text);
02562 }
02563 };
02564
02565
02566
02567 extern "C"
02568 char *new_command_generator(const char *text, int state)
02569 {
02570
02571 if (!state)
02572 {
02573 completion_string= lower_string(text);
02574 if (completion_string.size() == 0)
02575 {
02576 completion_iter= completion_map.begin();
02577 completion_end= completion_map.end();
02578 }
02579 else
02580 {
02581 completion_iter= find_if(completion_map.begin(), completion_map.end(),
02582 CompletionMatch<equal_to<string> >(completion_string));
02583 completion_end= find_if(completion_iter, completion_map.end(),
02584 CompletionMatch<not_equal_to<string> >(completion_string));
02585 }
02586 }
02587 if (completion_iter == completion_end || (size_t)state > completion_map.size())
02588 return NULL;
02589 char *result= (char *)malloc((*completion_iter).second.size()+1);
02590 strcpy(result, (*completion_iter).second.c_str());
02591 completion_iter++;
02592 return result;
02593 }
02594
02595
02596
02597 static void build_completion_hash(bool rehash, bool write_info)
02598 {
02599 Commands *cmd=commands;
02600 drizzle_return_t ret;
02601 drizzle_result_st databases,tables,fields;
02602 drizzle_row_t database_row,table_row;
02603 string tmp_str, tmp_str_lower;
02604 std::string query;
02605
02606 if (status.getBatch() || quick || current_db.empty())
02607 return;
02608 if (!rehash)
02609 return;
02610
02611 completion_map.clear();
02612
02613
02614 while (cmd->getName()) {
02615 tmp_str= cmd->getName();
02616 tmp_str_lower= lower_string(tmp_str);
02617 completion_map[tmp_str_lower]= tmp_str;
02618 cmd++;
02619 }
02620
02621
02622
02623
02624 if (drizzle_query_str(con, &databases, "select schema_name from information_schema.schemata", &ret) != NULL)
02625 {
02626 if (ret == DRIZZLE_RETURN_OK)
02627 {
02628 if (drizzle_result_buffer(&databases) != DRIZZLE_RETURN_OK)
02629 {
02630 put_info(drizzle_error(drizzle),INFO_INFO,0,0);
02631 }
02632 else
02633 {
02634 while ((database_row=drizzle_row_next(&databases)))
02635 {
02636 tmp_str= database_row[0];
02637 tmp_str_lower= lower_string(tmp_str);
02638 completion_map[tmp_str_lower]= tmp_str;
02639 }
02640 }
02641 }
02642
02643 drizzle_result_free(&databases);
02644 }
02645
02646 query= "select table_name, column_name from information_schema.columns where table_schema='";
02647 query.append(current_db);
02648 query.append("' order by table_name");
02649
02650 if (drizzle_query(con, &fields, query.c_str(), query.length(), &ret) != NULL)
02651 {
02652 if (ret == DRIZZLE_RETURN_OK &&
02653 drizzle_result_buffer(&fields) == DRIZZLE_RETURN_OK)
02654 {
02655 if (drizzle_result_row_count(&tables) > 0 && !opt_silent && write_info)
02656 {
02657 tee_fprintf(stdout,
02658 _("Reading table information for completion of "
02659 "table and column names\n"
02660 "You can turn off this feature to get a quicker "
02661 "startup with -A\n\n"));
02662 }
02663
02664 std::string table_name;
02665 while ((table_row=drizzle_row_next(&fields)))
02666 {
02667 if (table_name.compare(table_row[0]) != 0)
02668 {
02669 tmp_str= table_row[0];
02670 tmp_str_lower= lower_string(tmp_str);
02671 completion_map[tmp_str_lower]= tmp_str;
02672 table_name= table_row[0];
02673 }
02674 tmp_str= table_row[0];
02675 tmp_str.append(".");
02676 tmp_str.append(table_row[1]);
02677 tmp_str_lower= lower_string(tmp_str);
02678 completion_map[tmp_str_lower]= tmp_str;
02679
02680 tmp_str= table_row[1];
02681 tmp_str_lower= lower_string(tmp_str);
02682 completion_map[tmp_str_lower]= tmp_str;
02683 }
02684 }
02685 }
02686 drizzle_result_free(&fields);
02687 completion_iter= completion_map.begin();
02688 }
02689
02690
02691
02692
02693 static int reconnect(void)
02694 {
02695 if (opt_reconnect)
02696 {
02697 put_info(_("No connection. Trying to reconnect..."),INFO_INFO,0,0);
02698 (void) com_connect((string *)0, 0);
02699 if (opt_rehash && connected)
02700 com_rehash(NULL, NULL);
02701 }
02702 if (! connected)
02703 return put_info(_("Can't connect to the server\n"),INFO_ERROR,0,0);
02704 return 0;
02705 }
02706
02707 static void get_current_db(void)
02708 {
02709 drizzle_return_t ret;
02710 drizzle_result_st res;
02711
02712 current_db.erase();
02713 current_db= "";
02714
02715 if (drizzle_query_str(con, &res, "SELECT DATABASE()", &ret) != NULL)
02716 {
02717 if (ret == DRIZZLE_RETURN_OK &&
02718 drizzle_result_buffer(&res) == DRIZZLE_RETURN_OK)
02719 {
02720 drizzle_row_t row= drizzle_row_next(&res);
02721 if (row[0])
02722 current_db= row[0];
02723 drizzle_result_free(&res);
02724 }
02725 }
02726 }
02727
02728
02729
02730
02731
02732 int drizzleclient_real_query_for_lazy(const char *buf, size_t length,
02733 drizzle_result_st *result,
02734 uint32_t *error_code)
02735 {
02736 drizzle_return_t ret;
02737
02738 for (uint32_t retry=0;; retry++)
02739 {
02740 int error;
02741 if (drizzle_query(con, result, buf, length, &ret) != NULL and
02742 ret == DRIZZLE_RETURN_OK)
02743 {
02744 return 0;
02745 }
02746 error= put_error(con, result);
02747
02748 if (ret == DRIZZLE_RETURN_ERROR_CODE)
02749 {
02750 *error_code= drizzle_result_error_code(result);
02751 drizzle_result_free(result);
02752 }
02753
02754 if (ret != DRIZZLE_RETURN_LOST_CONNECTION || retry > 1 ||
02755 !opt_reconnect)
02756 {
02757 return error;
02758 }
02759
02760 if (reconnect())
02761 return error;
02762 }
02763 }
02764
02765 int drizzleclient_store_result_for_lazy(drizzle_result_st *result)
02766 {
02767 if (drizzle_result_buffer(result) == DRIZZLE_RETURN_OK)
02768 {
02769 return 0;
02770 }
02771
02772 if (drizzle_con_error(con)[0])
02773 {
02774 int ret= put_error(con, result);
02775 drizzle_result_free(result);
02776 return ret;
02777 }
02778
02779 return 0;
02780 }
02781
02782 static int
02783 com_help(string *buffer, const char *)
02784 {
02785 int i, j;
02786 char buff[32], *end;
02787 std::vector<char> output_buff;
02788 output_buff.resize(512);
02789
02790 put_info(_("List of all Drizzle commands:"), INFO_INFO,0,0);
02791 if (!named_cmds)
02792 {
02793 snprintf(&output_buff[0], output_buff.size(),
02794 _("Note that all text commands must be first on line and end with '%s' or \\g"),
02795 delimiter);
02796 put_info(&output_buff[0], INFO_INFO, 0, 0);
02797 }
02798 for (i = 0; commands[i].getName(); i++)
02799 {
02800 end= strcpy(buff, commands[i].getName());
02801 end+= strlen(commands[i].getName());
02802 for (j= (int)strlen(commands[i].getName()); j < 10; j++)
02803 end= strcpy(end, " ")+1;
02804 if (commands[i].func)
02805 tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
02806 commands[i].getCmdChar(), _(commands[i].getDoc()));
02807 }
02808 tee_fprintf(stdout, "\n");
02809 buffer->clear();
02810 return 0;
02811 }
02812
02813
02814 static int
02815 com_clear(string *buffer, const char *)
02816 {
02817 if (status.getAddToHistory())
02818 fix_history(buffer);
02819 buffer->clear();
02820 return 0;
02821 }
02822
02823
02824
02825
02826
02827
02828
02829
02830 static int
02831 com_go(string *buffer, const char *)
02832 {
02833 char buff[200];
02834 drizzle_result_st result;
02835 drizzle_return_t ret;
02836 uint32_t warnings= 0;
02837 boost::posix_time::ptime timer;
02838 uint32_t error= 0;
02839 uint32_t error_code= 0;
02840 int err= 0;
02841
02842 interrupted_query= false;
02843
02844
02845 remove_cntrl(buffer);
02846
02847 if (buffer->empty())
02848 {
02849
02850 if (status.getBatch())
02851 return 0;
02852 return put_info(_("No query specified\n"),INFO_ERROR,0,0);
02853
02854 }
02855 if (!connected && reconnect())
02856 {
02857
02858 buffer->clear();
02859 return opt_reconnect ? -1 : 1;
02860 }
02861 if (verbose)
02862 (void) com_print(buffer, 0);
02863
02864 if (skip_updates &&
02865 ((buffer->length() < 4) || (buffer->find( "SET ") != 0)))
02866 {
02867 (void) put_info(_("Ignoring query to other database"),INFO_INFO,0,0);
02868 return 0;
02869 }
02870
02871 timer=start_timer();
02872 executing_query= true;
02873 error= drizzleclient_real_query_for_lazy(buffer->c_str(),buffer->length(),&result, &error_code);
02874
02875 if (status.getAddToHistory())
02876 {
02877 buffer->append(vertical ? "\\G" : delimiter);
02878
02879 fix_history(buffer);
02880 }
02881
02882 buffer->clear();
02883
02884 if (error)
02885 goto end;
02886
02887 do
02888 {
02889 char *pos;
02890
02891 if (quick)
02892 {
02893 if (drizzle_column_buffer(&result) != DRIZZLE_RETURN_OK)
02894 {
02895 error= put_error(con, &result);
02896 goto end;
02897 }
02898 }
02899 else
02900 {
02901 error= drizzleclient_store_result_for_lazy(&result);
02902 if (error)
02903 goto end;
02904 }
02905
02906 string time_buff("");
02907 if (verbose >= 3 || !opt_silent)
02908 drizzle_end_timer(timer,time_buff);
02909
02910
02911 if (drizzle_result_column_count(&result) > 0)
02912 {
02913 if (!quick && drizzle_result_row_count(&result) == 0 &&
02914 !column_types_flag)
02915 {
02916 strcpy(buff, _("Empty set"));
02917 }
02918 else
02919 {
02920 init_pager();
02921 if (vertical || (auto_vertical_output &&
02922 (terminal_width < get_result_width(&result))))
02923 print_table_data_vertically(&result);
02924 else if (opt_silent && verbose <= 2 && !output_tables)
02925 print_tab_data(&result);
02926 else
02927 print_table_data(&result);
02928 sprintf(buff,
02929 ngettext("%ld row in set","%ld rows in set",
02930 (long) drizzle_result_row_count(&result)),
02931 (long) drizzle_result_row_count(&result));
02932 end_pager();
02933 if (drizzle_result_error_code(&result))
02934 error= put_error(con, &result);
02935 }
02936 }
02937 else if (drizzle_result_affected_rows(&result) == ~(uint64_t) 0)
02938 strcpy(buff,_("Query OK"));
02939 else
02940 sprintf(buff, ngettext("Query OK, %ld row affected",
02941 "Query OK, %ld rows affected",
02942 (long) drizzle_result_affected_rows(&result)),
02943 (long) drizzle_result_affected_rows(&result));
02944
02945 pos= strchr(buff, '\0');
02946 if ((warnings= drizzle_result_warning_count(&result)))
02947 {
02948 *pos++= ',';
02949 *pos++= ' ';
02950 char warnings_buff[20];
02951 memset(warnings_buff,0,20);
02952 sprintf(warnings_buff, "%d", warnings);
02953 strcpy(pos, warnings_buff);
02954 pos+= strlen(warnings_buff);
02955 pos= strcpy(pos, " warning")+8;
02956 if (warnings != 1)
02957 *pos++= 's';
02958 }
02959 strcpy(pos, time_buff.c_str());
02960 put_info(buff,INFO_RESULT,0,0);
02961 if (strcmp(drizzle_result_info(&result), ""))
02962 put_info(drizzle_result_info(&result),INFO_RESULT,0,0);
02963 put_info("",INFO_RESULT,0,0);
02964
02965 if (unbuffered)
02966 fflush(stdout);
02967 drizzle_result_free(&result);
02968
02969 if (drizzle_con_status(con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS)
02970 {
02971 if (drizzle_result_read(con, &result, &ret) == NULL ||
02972 ret != DRIZZLE_RETURN_OK)
02973 {
02974 if (ret == DRIZZLE_RETURN_ERROR_CODE)
02975 {
02976 error_code= drizzle_result_error_code(&result);
02977 drizzle_result_free(&result);
02978 }
02979
02980 error= put_error(con, NULL);
02981 goto end;
02982 }
02983 }
02984
02985 } while (drizzle_con_status(con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS);
02986 if (err >= 1)
02987 {
02988 error= put_error(con, NULL);
02989 }
02990
02991 end:
02992
02993
02994 if (show_warnings == 1 && (warnings >= 1 || error))
02995 print_warnings(error_code);
02996
02997 if (!error && !status.getBatch() and
02998 drizzle_con_status(con) & DRIZZLE_CON_STATUS_DB_DROPPED)
02999 {
03000 get_current_db();
03001 }
03002
03003 executing_query= false;
03004 return error;
03005 }
03006
03007
03008 static void init_pager()
03009 {
03010 if (opt_nopager == false)
03011 {
03012 if (!(PAGER= popen(pager.c_str(), "w")))
03013 {
03014 tee_fprintf(stdout,_( "popen() failed! defaulting PAGER to stdout!\n"));
03015 PAGER= stdout;
03016 }
03017 }
03018 else
03019 {
03020 PAGER= stdout;
03021 }
03022 }
03023
03024 static void end_pager()
03025 {
03026 if (!opt_nopager)
03027 pclose(PAGER);
03028 }
03029
03030
03031 static void init_tee(const char *file_name)
03032 {
03033 FILE* new_outfile;
03034 if (opt_outfile)
03035 {
03036 end_tee();
03037 }
03038
03039 if ((new_outfile= fopen(file_name, "a")) == NULL)
03040 {
03041 tee_fprintf(stdout, _("Error logging to file '%s'\n"), file_name);
03042 return;
03043 }
03044 OUTFILE = new_outfile;
03045 outfile= file_name;
03046 tee_fprintf(stdout, _("Logging to file '%s'\n"), file_name);
03047 opt_outfile= 1;
03048
03049 return;
03050 }
03051
03052
03053 static void end_tee()
03054 {
03055 fclose(OUTFILE);
03056 OUTFILE= 0;
03057 opt_outfile= 0;
03058 return;
03059 }
03060
03061
03062 static int
03063 com_ego(string *buffer,const char *line)
03064 {
03065 int result;
03066 bool oldvertical=vertical;
03067 vertical=1;
03068 result=com_go(buffer,line);
03069 vertical=oldvertical;
03070 return result;
03071 }
03072
03073
03074 static const char *fieldtype2str(drizzle_column_type_t type)
03075 {
03076 switch (type) {
03077 case DRIZZLE_COLUMN_TYPE_BLOB: return "BLOB";
03078 case DRIZZLE_COLUMN_TYPE_DATE: return "DATE";
03079 case DRIZZLE_COLUMN_TYPE_DATETIME: return "DATETIME";
03080 case DRIZZLE_COLUMN_TYPE_NEWDECIMAL: return "DECIMAL";
03081 case DRIZZLE_COLUMN_TYPE_DOUBLE: return "DOUBLE";
03082 case DRIZZLE_COLUMN_TYPE_ENUM: return "ENUM";
03083 case DRIZZLE_COLUMN_TYPE_LONG: return "LONG";
03084 case DRIZZLE_COLUMN_TYPE_LONGLONG: return "LONGLONG";
03085 case DRIZZLE_COLUMN_TYPE_NULL: return "NULL";
03086 case DRIZZLE_COLUMN_TYPE_TIMESTAMP: return "TIMESTAMP";
03087 default: return "?-unknown-?";
03088 }
03089 }
03090
03091 static char *fieldflags2str(uint32_t f) {
03092 static char buf[1024];
03093 char *s=buf;
03094 *s=0;
03095 #define ff2s_check_flag(X) \
03096 if (f & DRIZZLE_COLUMN_FLAGS_ ## X) { s=strcpy(s, # X " ")+strlen(# X " "); \
03097 f &= ~ DRIZZLE_COLUMN_FLAGS_ ## X; }
03098 ff2s_check_flag(NOT_NULL);
03099 ff2s_check_flag(PRI_KEY);
03100 ff2s_check_flag(UNIQUE_KEY);
03101 ff2s_check_flag(MULTIPLE_KEY);
03102 ff2s_check_flag(BLOB);
03103 ff2s_check_flag(UNSIGNED);
03104 ff2s_check_flag(BINARY);
03105 ff2s_check_flag(ENUM);
03106 ff2s_check_flag(AUTO_INCREMENT);
03107 ff2s_check_flag(TIMESTAMP);
03108 ff2s_check_flag(SET);
03109 ff2s_check_flag(NO_DEFAULT_VALUE);
03110 ff2s_check_flag(NUM);
03111 ff2s_check_flag(PART_KEY);
03112 ff2s_check_flag(GROUP);
03113 ff2s_check_flag(UNIQUE);
03114 ff2s_check_flag(BINCMP);
03115 ff2s_check_flag(ON_UPDATE_NOW);
03116 #undef ff2s_check_flag
03117 if (f)
03118 sprintf(s, " unknows=0x%04x", f);
03119 return buf;
03120 }
03121
03122 static void
03123 print_field_types(drizzle_result_st *result)
03124 {
03125 drizzle_column_st *field;
03126 uint32_t i=0;
03127
03128 while ((field = drizzle_column_next(result)))
03129 {
03130 tee_fprintf(PAGER, _("Field %3u: `%s`\n"
03131 "Catalog: `%s`\n"
03132 "Schema: `%s`\n"
03133 "Table: `%s`\n"
03134 "Org_table: `%s`\n"
03135 "Type: UTF-8\n"
03136 "Collation: %s (%u)\n"
03137 "Length: %lu\n"
03138 "Max_length: %lu\n"
03139 "Decimals: %u\n"
03140 "Flags: %s\n\n"),
03141 ++i,
03142 drizzle_column_name(field), drizzle_column_catalog(field),
03143 drizzle_column_db(field), drizzle_column_table(field),
03144 drizzle_column_orig_table(field),
03145 fieldtype2str(drizzle_column_type(field)),
03146 drizzle_column_charset(field), drizzle_column_size(field),
03147 drizzle_column_max_size(field), drizzle_column_decimals(field),
03148 fieldflags2str(drizzle_column_flags(field)));
03149 }
03150 tee_puts("", PAGER);
03151 }
03152
03153 static void
03154 print_table_data(drizzle_result_st *result)
03155 {
03156 drizzle_row_t cur;
03157 drizzle_return_t ret;
03158 drizzle_column_st *field;
03159 std::vector<bool> num_flag;
03160 std::vector<bool> boolean_flag;
03161 std::vector<bool> ansi_boolean_flag;
03162 string separator;
03163
03164 separator.reserve(256);
03165
03166 num_flag.resize(drizzle_result_column_count(result));
03167 boolean_flag.resize(drizzle_result_column_count(result));
03168 ansi_boolean_flag.resize(drizzle_result_column_count(result));
03169 if (column_types_flag)
03170 {
03171 print_field_types(result);
03172 if (!drizzle_result_row_count(result))
03173 return;
03174 drizzle_column_seek(result,0);
03175 }
03176 separator.append("+");
03177 while ((field = drizzle_column_next(result)))
03178 {
03179 uint32_t x, length= 0;
03180
03181 if (column_names)
03182 {
03183 uint32_t name_length= strlen(drizzle_column_name(field));
03184
03185
03186
03187
03188 length= drizzled::utf8::char_length(drizzle_column_name(field));
03189
03190 if (name_length == drizzle_column_max_size(field))
03191 {
03192 if (length < drizzle_column_max_size(field))
03193 drizzle_column_set_max_size(field, length);
03194 }
03195 else
03196 {
03197 length= name_length;
03198 }
03199 }
03200
03201 if (quick)
03202 length=max(length,drizzle_column_size(field));
03203 else
03204 length=max(length,(uint32_t)drizzle_column_max_size(field));
03205 if (length < 4 &&
03206 !(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
03207 {
03208
03209 length=4;
03210 }
03211 if ((length < 5) and
03212 (server_type == ServerDetect::SERVER_DRIZZLE_FOUND) and
03213 (drizzle_column_type(field) == DRIZZLE_COLUMN_TYPE_TINY) and
03214 (drizzle_column_type(field) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
03215 {
03216
03217 length= 5;
03218 }
03219 drizzle_column_set_max_size(field, length);
03220
03221 for (x=0; x< (length+2); x++)
03222 separator.append("-");
03223 separator.append("+");
03224 }
03225
03226 tee_puts((char*) separator.c_str(), PAGER);
03227 if (column_names)
03228 {
03229 drizzle_column_seek(result,0);
03230 (void) tee_fputs("|", PAGER);
03231 for (uint32_t off=0; (field = drizzle_column_next(result)) ; off++)
03232 {
03233 uint32_t name_length= (uint32_t) strlen(drizzle_column_name(field));
03234 uint32_t numcells= drizzled::utf8::char_length(drizzle_column_name(field));
03235 uint32_t display_length= drizzle_column_max_size(field) + name_length -
03236 numcells;
03237 tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
03238 MAX_COLUMN_LENGTH),
03239 drizzle_column_name(field));
03240 num_flag[off]= ((drizzle_column_type(field) <= DRIZZLE_COLUMN_TYPE_LONGLONG) ||
03241 (drizzle_column_type(field) == DRIZZLE_COLUMN_TYPE_NEWDECIMAL));
03242 if ((server_type == ServerDetect::SERVER_DRIZZLE_FOUND) and
03243 (drizzle_column_type(field) == DRIZZLE_COLUMN_TYPE_TINY))
03244 {
03245 if ((drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
03246 {
03247 ansi_boolean_flag[off]= true;
03248 }
03249 else
03250 {
03251 ansi_boolean_flag[off]= false;
03252 }
03253 boolean_flag[off]= true;
03254 num_flag[off]= false;
03255 }
03256 else
03257 {
03258 boolean_flag[off]= false;
03259 }
03260 }
03261 (void) tee_fputs("\n", PAGER);
03262 tee_puts((char*) separator.c_str(), PAGER);
03263 }
03264
03265 while (1)
03266 {
03267 if (quick)
03268 {
03269 cur= drizzle_row_buffer(result, &ret);
03270 if (ret != DRIZZLE_RETURN_OK)
03271 {
03272 (void)put_error(con, result);
03273 break;
03274 }
03275 }
03276 else
03277 cur= drizzle_row_next(result);
03278
03279 if (cur == NULL || interrupted_query)
03280 break;
03281
03282 size_t *lengths= drizzle_row_field_sizes(result);
03283 (void) tee_fputs("| ", PAGER);
03284 drizzle_column_seek(result, 0);
03285 for (uint32_t off= 0; off < drizzle_result_column_count(result); off++)
03286 {
03287 const char *buffer;
03288 uint32_t data_length;
03289 uint32_t field_max_length;
03290 uint32_t visible_length;
03291 uint32_t extra_padding;
03292
03293 if (cur[off] == NULL)
03294 {
03295 buffer= "NULL";
03296 data_length= 4;
03297 }
03298 else if (boolean_flag[off])
03299 {
03300 if (strncmp(cur[off],"1", 1) == 0)
03301 {
03302 if (ansi_boolean_flag[off])
03303 {
03304 buffer= "YES";
03305 data_length= 3;
03306 }
03307 else
03308 {
03309 buffer= "TRUE";
03310 data_length= 4;
03311 }
03312 }
03313 else
03314 {
03315 if (ansi_boolean_flag[off])
03316 {
03317 buffer= "NO";
03318 data_length= 2;
03319 }
03320 else
03321 {
03322 buffer= "FALSE";
03323 data_length= 5;
03324 }
03325 }
03326 }
03327 else
03328 {
03329 buffer= cur[off];
03330 data_length= (uint32_t) lengths[off];
03331 }
03332
03333 field= drizzle_column_next(result);
03334 field_max_length= drizzle_column_max_size(field);
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344 visible_length= drizzled::utf8::char_length(buffer);
03345 extra_padding= data_length - visible_length;
03346
03347 if (field_max_length > MAX_COLUMN_LENGTH)
03348 tee_print_sized_data(buffer, data_length, MAX_COLUMN_LENGTH+extra_padding, false);
03349 else
03350 {
03351 if (num_flag[off] != 0)
03352 tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, true);
03353 else
03354 tee_print_sized_data(buffer, data_length,
03355 field_max_length+extra_padding, false);
03356 }
03357 tee_fputs(" | ", PAGER);
03358 }
03359 (void) tee_fputs("\n", PAGER);
03360 if (quick)
03361 drizzle_row_free(result, cur);
03362 }
03363 tee_puts(separator.c_str(), PAGER);
03364 }
03365
03382 static int get_field_disp_length(drizzle_column_st *field)
03383 {
03384 uint32_t length= column_names ? strlen(drizzle_column_name(field)) : 0;
03385
03386 if (quick)
03387 length= max(length, drizzle_column_size(field));
03388 else
03389 length= max(length, (uint32_t)drizzle_column_max_size(field));
03390
03391 if (length < 4 &&
03392 !(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
03393 {
03394 length= 4;
03395 }
03396
03397 return length;
03398 }
03399
03408 static int get_result_width(drizzle_result_st *result)
03409 {
03410 unsigned int len= 0;
03411 drizzle_column_st *field;
03412 uint16_t offset;
03413
03414 offset= drizzle_column_current(result);
03415 assert(offset == 0);
03416
03417 while ((field= drizzle_column_next(result)) != NULL)
03418 len+= get_field_disp_length(field) + 3;
03419
03420 (void) drizzle_column_seek(result, offset);
03421
03422 return len + 1;
03423 }
03424
03425 static void
03426 tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified)
03427 {
03428
03429
03430
03431
03432
03433 unsigned int i;
03434 const char *p;
03435
03436 if (right_justified)
03437 for (i= data_length; i < total_bytes_to_send; i++)
03438 tee_putc((int)' ', PAGER);
03439
03440 for (i= 0, p= data; i < data_length; i+= 1, p+= 1)
03441 {
03442 if (*p == '\0')
03443 tee_putc((int)' ', PAGER);
03444 else
03445 tee_putc((int)*p, PAGER);
03446 }
03447
03448 if (! right_justified)
03449 for (i= data_length; i < total_bytes_to_send; i++)
03450 tee_putc((int)' ', PAGER);
03451 }
03452
03453
03454
03455 static void
03456 print_table_data_vertically(drizzle_result_st *result)
03457 {
03458 drizzle_row_t cur;
03459 drizzle_return_t ret;
03460 uint32_t max_length=0;
03461 drizzle_column_st *field;
03462
03463 while ((field = drizzle_column_next(result)))
03464 {
03465 uint32_t length= strlen(drizzle_column_name(field));
03466 if (length > max_length)
03467 max_length= length;
03468 drizzle_column_set_max_size(field, length);
03469 }
03470
03471 for (uint32_t row_count=1;; row_count++)
03472 {
03473 if (quick)
03474 {
03475 cur= drizzle_row_buffer(result, &ret);
03476 if (ret != DRIZZLE_RETURN_OK)
03477 {
03478 (void)put_error(con, result);
03479 break;
03480 }
03481 }
03482 else
03483 cur= drizzle_row_next(result);
03484
03485 if (cur == NULL || interrupted_query)
03486 break;
03487 drizzle_column_seek(result,0);
03488 tee_fprintf(PAGER,
03489 "*************************** %d. row ***************************\n", row_count);
03490 for (uint32_t off=0; off < drizzle_result_column_count(result); off++)
03491 {
03492 field= drizzle_column_next(result);
03493 tee_fprintf(PAGER, "%*s: ",(int) max_length,drizzle_column_name(field));
03494 tee_fprintf(PAGER, "%s\n",cur[off] ? (char*) cur[off] : "NULL");
03495 }
03496 if (quick)
03497 drizzle_row_free(result, cur);
03498 }
03499 }
03500
03501
03502
03503
03504 static void print_warnings(uint32_t error_code)
03505 {
03506 const char *query;
03507 drizzle_result_st result;
03508 drizzle_row_t cur;
03509 uint64_t num_rows;
03510 uint32_t new_code= 0;
03511 FILE *out;
03512
03513
03514 query= "show warnings";
03515 drizzleclient_real_query_for_lazy(query, strlen(query),&result,&new_code);
03516 drizzleclient_store_result_for_lazy(&result);
03517
03518
03519 if (!(num_rows= drizzle_result_row_count(&result)))
03520 goto end;
03521
03522 cur= drizzle_row_next(&result);
03523
03524
03525
03526
03527
03528
03529
03530 if (!cur || (num_rows == 1 &&
03531 error_code == (uint32_t) strtoul(cur[1], NULL, 10)))
03532 {
03533 goto end;
03534 }
03535
03536
03537 if (status.getBatch())
03538 {
03539 out= stderr;
03540 }
03541 else
03542 {
03543 init_pager();
03544 out= PAGER;
03545 }
03546 do
03547 {
03548 tee_fprintf(out, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]);
03549 } while ((cur= drizzle_row_next(&result)));
03550
03551 if (not status.getBatch())
03552 end_pager();
03553
03554 end:
03555 drizzle_result_free(&result);
03556 }
03557
03558
03559 static void
03560 safe_put_field(const char *pos,uint32_t length)
03561 {
03562 if (!pos)
03563 tee_fputs("NULL", PAGER);
03564 else
03565 {
03566 if (opt_raw_data)
03567 tee_fputs(pos, PAGER);
03568 else for (const char *end=pos+length ; pos != end ; pos++)
03569 {
03570 int l;
03571 if ((l = drizzled::utf8::sequence_length(*pos)))
03572 {
03573 while (l--)
03574 tee_putc(*pos++, PAGER);
03575 pos--;
03576 continue;
03577 }
03578 if (!*pos)
03579 tee_fputs("\\0", PAGER);
03580 else if (*pos == '\t')
03581 tee_fputs("\\t", PAGER);
03582 else if (*pos == '\n')
03583 tee_fputs("\\n", PAGER);
03584 else if (*pos == '\\')
03585 tee_fputs("\\\\", PAGER);
03586 else
03587 tee_putc(*pos, PAGER);
03588 }
03589 }
03590 }
03591
03592
03593 static void
03594 print_tab_data(drizzle_result_st *result)
03595 {
03596 drizzle_row_t cur;
03597 drizzle_return_t ret;
03598 drizzle_column_st *field;
03599 size_t *lengths;
03600 std::vector<bool> boolean_flag;
03601 std::vector<bool> ansi_boolean_flag;
03602
03603 boolean_flag.resize(drizzle_result_column_count(result));
03604 ansi_boolean_flag.resize(drizzle_result_column_count(result));
03605
03606 int first=0;
03607 for (uint32_t off= 0; (field = drizzle_column_next(result)); off++)
03608 {
03609 if (opt_silent < 2 && column_names)
03610 {
03611 if (first++)
03612 (void) tee_fputs("\t", PAGER);
03613 (void) tee_fputs(drizzle_column_name(field), PAGER);
03614 }
03615 if ((server_type == ServerDetect::SERVER_DRIZZLE_FOUND) and
03616 (drizzle_column_type(field) == DRIZZLE_COLUMN_TYPE_TINY))
03617 {
03618 if ((drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_UNSIGNED))
03619 {
03620 ansi_boolean_flag[off]= true;
03621 }
03622 else
03623 {
03624 ansi_boolean_flag[off]= false;
03625 }
03626 boolean_flag[off]= true;
03627 }
03628 else
03629 {
03630 boolean_flag[off]= false;
03631 }
03632 }
03633 if (opt_silent < 2 && column_names)
03634 {
03635 (void) tee_fputs("\n", PAGER);
03636 }
03637 while (1)
03638 {
03639 if (quick)
03640 {
03641 cur= drizzle_row_buffer(result, &ret);
03642 if (ret != DRIZZLE_RETURN_OK)
03643 {
03644 (void)put_error(con, result);
03645 break;
03646 }
03647 }
03648 else
03649 cur= drizzle_row_next(result);
03650
03651 if (cur == NULL)
03652 break;
03653
03654 lengths= drizzle_row_field_sizes(result);
03655 drizzle_column_seek(result, 0);
03656 for (uint32_t off=0 ; off < drizzle_result_column_count(result); off++)
03657 {
03658 if (off != 0)
03659 (void) tee_fputs("\t", PAGER);
03660 if (boolean_flag[off])
03661 {
03662 if (strncmp(cur[off],"1", 1) == 0)
03663 {
03664 if (ansi_boolean_flag[off])
03665 {
03666 safe_put_field("YES", 3);
03667 }
03668 else
03669 {
03670 safe_put_field("TRUE", 4);
03671 }
03672 }
03673 else
03674 {
03675 if (ansi_boolean_flag[off])
03676 {
03677 safe_put_field("NO", 2);
03678 }
03679 else
03680 {
03681 safe_put_field("FALSE", 5);
03682 }
03683 }
03684 }
03685 else
03686 {
03687 safe_put_field(cur[off], lengths[off]);
03688 }
03689 }
03690 (void) tee_fputs("\n", PAGER);
03691 if (quick)
03692 drizzle_row_free(result, cur);
03693 }
03694 }
03695
03696 static int
03697 com_tee(string *, const char *line )
03698 {
03699 char file_name[FN_REFLEN], *end;
03700 const char *param;
03701
03702 if (status.getBatch())
03703 return 0;
03704 while (isspace(*line))
03705 line++;
03706 if (!(param =strchr(line, ' ')))
03707 {
03708 if (outfile.empty())
03709 {
03710 printf(_("No previous outfile available, you must give a filename!\n"));
03711 return 0;
03712 }
03713 else if (opt_outfile)
03714 {
03715 tee_fprintf(stdout, _("Currently logging to file '%s'\n"), outfile.c_str());
03716 return 0;
03717 }
03718 else
03719 param= outfile.c_str();
03720 }
03721
03722
03723
03724 while (isspace(*param))
03725 param++;
03726 strncpy(file_name, param, sizeof(file_name) - 1);
03727 end= file_name + strlen(file_name);
03728
03729 while (end > file_name && (isspace(end[-1]) ||
03730 iscntrl(end[-1])))
03731 end--;
03732 end[0]= 0;
03733 if (end == file_name)
03734 {
03735 printf(_("No outfile specified!\n"));
03736 return 0;
03737 }
03738 init_tee(file_name);
03739 return 0;
03740 }
03741
03742
03743 static int
03744 com_notee(string *, const char *)
03745 {
03746 if (opt_outfile)
03747 end_tee();
03748 tee_fprintf(stdout, _("Outfile disabled.\n"));
03749 return 0;
03750 }
03751
03752
03753
03754
03755
03756 static int
03757 com_pager(string *, const char *line)
03758 {
03759 const char *param;
03760
03761 if (status.getBatch())
03762 return 0;
03763
03764 while (isspace(*line))
03765 line++;
03766
03767 param= strchr(line, ' ');
03768
03769 while (param && isspace(*param))
03770 param++;
03771 if (!param || (*param == '\0'))
03772 {
03773 if (!default_pager_set)
03774 {
03775 tee_fprintf(stdout, _("Default pager wasn't set, using stdout.\n"));
03776 opt_nopager=1;
03777 pager= "stdout";
03778 PAGER= stdout;
03779 return 0;
03780 }
03781 pager= default_pager;
03782 }
03783 else
03784 {
03785 string pager_name(param);
03786 string::iterator end= pager_name.end();
03787 while (end > pager_name.begin() &&
03788 (isspace(*(end-1)) || iscntrl(*(end-1))))
03789 --end;
03790 pager_name.erase(end, pager_name.end());
03791 pager= pager_name;
03792 default_pager= pager_name;
03793 }
03794 opt_nopager=0;
03795 tee_fprintf(stdout, _("PAGER set to '%s'\n"), pager.c_str());
03796 return 0;
03797 }
03798
03799
03800 static int
03801 com_nopager(string *, const char *)
03802 {
03803 pager= "stdout";
03804 opt_nopager=1;
03805 PAGER= stdout;
03806 tee_fprintf(stdout, _("PAGER set to stdout\n"));
03807 return 0;
03808 }
03809
03810
03811
03812 static int
03813 com_quit(string *, const char *)
03814 {
03815
03816 status.setExitStatus(0);
03817 return 1;
03818 }
03819
03820 static int
03821 com_rehash(string *, const char *)
03822 {
03823 build_completion_hash(1, 0);
03824 return 0;
03825 }
03826
03827
03828
03829 static int
03830 com_print(string *buffer,const char *)
03831 {
03832 tee_puts("--------------", stdout);
03833 (void) tee_fputs(buffer->c_str(), stdout);
03834 if ( (buffer->length() == 0)
03835 || (buffer->c_str())[(buffer->length())-1] != '\n')
03836 tee_putc('\n', stdout);
03837 tee_puts("--------------\n", stdout);
03838
03839 return 0;
03840 }
03841
03842
03843 static int
03844 com_connect(string *buffer, const char *line)
03845 {
03846 char *tmp, buff[256];
03847 bool save_rehash= opt_rehash;
03848 int error;
03849
03850 memset(buff, 0, sizeof(buff));
03851 if (buffer)
03852 {
03853
03854
03855
03856
03857 tmp= strncpy(buff, line, sizeof(buff)-2);
03858 #ifdef EXTRA_DEBUG
03859 tmp[1]= 0;
03860 #endif
03861 tmp= get_arg(buff, 0);
03862 if (tmp && *tmp)
03863 {
03864 current_db= tmp;
03865 tmp= get_arg(buff, 1);
03866 if (tmp)
03867 {
03868 current_host.erase();
03869 current_host=strdup(tmp);
03870 }
03871 }
03872 else
03873 {
03874
03875 opt_rehash= 0;
03876 }
03877
03878 assert(buffer!=NULL);
03879 buffer->clear();
03880 }
03881 else
03882 opt_rehash= 0;
03883 error=sql_connect(current_host, current_db, current_user, opt_password);
03884 opt_rehash= save_rehash;
03885
03886 if (connected)
03887 {
03888 sprintf(buff, _("Connection id: %u"), drizzle_con_thread_id(con));
03889 put_info(buff,INFO_INFO,0,0);
03890 sprintf(buff, _("Current schema: %.128s\n"),
03891 !current_db.empty() ? current_db.c_str() : _("*** NONE ***"));
03892 put_info(buff,INFO_INFO,0,0);
03893 }
03894 return error;
03895 }
03896
03897
03898 static int com_source(string *, const char *line)
03899 {
03900 char source_name[FN_REFLEN], *end;
03901 const char *param;
03902 LineBuffer *line_buff;
03903 int error;
03904 Status old_status;
03905 FILE *sql_file;
03906
03907
03908 while (isspace(*line))
03909 line++;
03910 if (!(param = strchr(line, ' ')))
03911 return put_info(_("Usage: \\. <filename> | source <filename>"),
03912 INFO_ERROR, 0,0);
03913 while (isspace(*param))
03914 param++;
03915 end= strncpy(source_name,param,sizeof(source_name)-1);
03916 end+= strlen(source_name);
03917 while (end > source_name && (isspace(end[-1]) ||
03918 iscntrl(end[-1])))
03919 end--;
03920 end[0]=0;
03921
03922
03923 if (!(sql_file = fopen(source_name, "r")))
03924 {
03925 char buff[FN_REFLEN+60];
03926 sprintf(buff, _("Failed to open file '%s', error: %d"), source_name,errno);
03927 return put_info(buff, INFO_ERROR, 0 ,0);
03928 }
03929
03930 line_buff= new LineBuffer(opt_max_input_line,sql_file);
03931
03932
03933 old_status=status;
03934 memset(&status, 0, sizeof(status));
03935
03936
03937 status.setBatch(old_status.getBatch());
03938 status.setLineBuff(line_buff);
03939 status.setFileName(source_name);
03940
03941 assert(glob_buffer!=NULL);
03942 glob_buffer->clear();
03943 error= read_and_execute(false);
03944
03945 status=old_status;
03946 fclose(sql_file);
03947 delete status.getLineBuff();
03948 line_buff=0;
03949 status.setLineBuff(0);
03950 return error;
03951 }
03952
03953
03954
03955 static int
03956 com_delimiter(string *, const char *line)
03957 {
03958 char buff[256];
03959
03960 strncpy(buff, line, sizeof(buff) - 1);
03961 char* tmp= get_arg(buff, 0);
03962
03963 if (!tmp || !*tmp)
03964 {
03965 put_info(_("DELIMITER must be followed by a 'delimiter' character or string"), INFO_ERROR, 0, 0);
03966 return 0;
03967 }
03968 else
03969 {
03970 if (strstr(tmp, "\\"))
03971 {
03972 put_info(_("DELIMITER cannot contain a backslash character"), INFO_ERROR, 0, 0);
03973 return 0;
03974 }
03975 }
03976 delimiter= strdup(tmp);
03977 delimiter_length= (int)strlen(delimiter);
03978 delimiter_str= delimiter;
03979 return 0;
03980 }
03981
03982
03983 static int
03984 com_use(string *, const char *line)
03985 {
03986 char *tmp, buff[FN_REFLEN + 1];
03987 int select_db;
03988 drizzle_result_st result;
03989 drizzle_return_t ret;
03990
03991 memset(buff, 0, sizeof(buff));
03992 strncpy(buff, line, sizeof(buff) - 1);
03993 tmp= get_arg(buff, 0);
03994 if (!tmp || !*tmp)
03995 {
03996 put_info(_("USE must be followed by a schema name"), INFO_ERROR, 0, 0);
03997 return 0;
03998 }
03999
04000
04001
04002
04003
04004 get_current_db();
04005
04006 if (current_db.empty() || strcmp(current_db.c_str(),tmp))
04007 {
04008 if (one_database)
04009 {
04010 skip_updates= 1;
04011 select_db= 0;
04012 }
04013 else
04014 select_db= 2;
04015 }
04016 else
04017 {
04018
04019
04020
04021
04022
04023
04024
04025 skip_updates= 0;
04026 select_db= 1;
04027 }
04028
04029 if (select_db)
04030 {
04031
04032
04033
04034
04035 if (!connected && reconnect())
04036 return opt_reconnect ? -1 : 1;
04037 for (bool try_again= true; try_again; try_again= false)
04038 {
04039 if (drizzle_select_db(con, &result, tmp, &ret) == NULL ||
04040 ret != DRIZZLE_RETURN_OK)
04041 {
04042 if (ret == DRIZZLE_RETURN_ERROR_CODE)
04043 {
04044 int error= put_error(con, &result);
04045 drizzle_result_free(&result);
04046 return error;
04047 }
04048
04049 if (ret != DRIZZLE_RETURN_LOST_CONNECTION || !try_again)
04050 {
04051 return put_error(con, NULL);
04052 }
04053
04054 if (reconnect())
04055 {
04056 return opt_reconnect ? -1 : 1;
04057 }
04058 }
04059 else
04060 drizzle_result_free(&result);
04061 }
04062 current_db= tmp;
04063 if (select_db > 1)
04064 build_completion_hash(opt_rehash, 1);
04065 }
04066
04067 put_info(_("Schema changed"),INFO_INFO, 0, 0);
04068 return 0;
04069 }
04070
04071 static int com_shutdown(string *, const char *)
04072 {
04073 drizzle_result_st result;
04074 drizzle_return_t ret;
04075
04076 if (verbose)
04077 {
04078 printf(_("shutting down drizzled"));
04079 if (opt_drizzle_port > 0)
04080 printf(_(" on port %d"), opt_drizzle_port);
04081 printf("... ");
04082 }
04083
04084 if (drizzle_shutdown(con, &result, DRIZZLE_SHUTDOWN_DEFAULT,
04085 &ret) == NULL || ret != DRIZZLE_RETURN_OK)
04086 {
04087 if (ret == DRIZZLE_RETURN_ERROR_CODE)
04088 {
04089 fprintf(stderr, _("shutdown failed; error: '%s'"), drizzle_result_error(&result));
04090 drizzle_result_free(&result);
04091 }
04092 else
04093 {
04094 fprintf(stderr, _("shutdown failed; error: '%s'"), drizzle_con_error(con));
04095 }
04096 return false;
04097 }
04098
04099 drizzle_result_free(&result);
04100
04101 if (verbose)
04102 printf(_("done\n"));
04103
04104 return false;
04105 }
04106
04107 static int
04108 com_warnings(string *, const char *)
04109 {
04110 show_warnings = 1;
04111 put_info(_("Show warnings enabled."),INFO_INFO, 0, 0);
04112 return 0;
04113 }
04114
04115 static int
04116 com_nowarnings(string *, const char *)
04117 {
04118 show_warnings = 0;
04119 put_info(_("Show warnings disabled."),INFO_INFO, 0, 0);
04120 return 0;
04121 }
04122
04123
04124
04125
04126
04127
04128
04129
04130
04131
04132
04133 char *get_arg(char *line, bool get_next_arg)
04134 {
04135 char *ptr, *start;
04136 bool quoted= 0, valid_arg= 0;
04137 char qtype= 0;
04138
04139 ptr= line;
04140 if (get_next_arg)
04141 {
04142 for (; *ptr; ptr++) ;
04143 if (*(ptr + 1))
04144 ptr++;
04145 }
04146 else
04147 {
04148
04149 while (isspace(*ptr))
04150 ptr++;
04151 if (*ptr == '\\')
04152 ptr+= 2;
04153 else
04154 while (*ptr &&!isspace(*ptr))
04155 ptr++;
04156 }
04157 if (!*ptr)
04158 return NULL;
04159 while (isspace(*ptr))
04160 ptr++;
04161 if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
04162 {
04163 qtype= *ptr;
04164 quoted= 1;
04165 ptr++;
04166 }
04167 for (start=ptr ; *ptr; ptr++)
04168 {
04169 if (*ptr == '\\' && ptr[1])
04170 {
04171
04172 strcpy(ptr, ptr+1);
04173 }
04174 else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
04175 {
04176 *ptr= 0;
04177 break;
04178 }
04179 }
04180 valid_arg= ptr != start;
04181 return valid_arg ? start : NULL;
04182 }
04183
04184
04185 static int
04186 sql_connect(const string &host, const string &database, const string &user, const string &password)
04187 {
04188 drizzle_return_t ret;
04189 if (connected)
04190 {
04191 connected= 0;
04192 drizzle_con_free(con);
04193 drizzle_free(drizzle);
04194 }
04195
04196 drizzle= drizzle_create();
04197 if (drizzle == NULL)
04198 {
04199 return 1;
04200 }
04201
04202 if ((con= drizzle_con_add_tcp(drizzle, host.c_str(),
04203 opt_drizzle_port, user.c_str(),
04204 password.c_str(), database.c_str(),
04205 global_con_options)) == NULL)
04206 {
04207 (void) put_error(con, NULL);
04208 (void) fflush(stdout);
04209 return 1;
04210 }
04211
04212 if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
04213 {
04214
04215 if (opt_silent < 2)
04216 {
04217 (void) put_error(con, NULL);
04218 (void) fflush(stdout);
04219 return ignore_errors ? -1 : 1;
04220 }
04221 return -1;
04222 }
04223 connected= 1;
04224
04225 ServerDetect server_detect(con);
04226 server_type= server_detect.getServerType();
04227
04228 build_completion_hash(opt_rehash, 1);
04229 return 0;
04230 }
04231
04232
04233 static int
04234 com_status(string *, const char *)
04235 {
04236
04237
04238
04239
04240 drizzle_result_st result;
04241 drizzle_return_t ret;
04242
04243 tee_puts("--------------", stdout);
04244 printf(_("Drizzle client %s build %s, for %s-%s (%s) using readline %s\n"),
04245 drizzle_version(), VERSION,
04246 HOST_VENDOR, HOST_OS, HOST_CPU,
04247 rl_library_version);
04248
04249 if (connected)
04250 {
04251 tee_fprintf(stdout, _("\nConnection id:\t\t%lu\n"),drizzle_con_thread_id(con));
04252
04253
04254
04255
04256 if (drizzle_query_str(con, &result, "select DATABASE(), USER() limit 1",
04257 &ret) != NULL && ret == DRIZZLE_RETURN_OK &&
04258 drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
04259 {
04260 drizzle_row_t cur=drizzle_row_next(&result);
04261 if (cur)
04262 {
04263 tee_fprintf(stdout, _("Current schema:\t%s\n"), cur[0] ? cur[0] : "");
04264 tee_fprintf(stdout, _("Current user:\t\t%s\n"), cur[1]);
04265 }
04266 drizzle_result_free(&result);
04267 }
04268 else if (ret == DRIZZLE_RETURN_ERROR_CODE)
04269 drizzle_result_free(&result);
04270 tee_puts(_("SSL:\t\t\tNot in use"), stdout);
04271 }
04272 else
04273 {
04274 vidattr(A_BOLD);
04275 tee_fprintf(stdout, _("\nNo connection\n"));
04276 vidattr(A_NORMAL);
04277 return 0;
04278 }
04279 if (skip_updates)
04280 {
04281 vidattr(A_BOLD);
04282 tee_fprintf(stdout, _("\nAll updates ignored to this schema\n"));
04283 vidattr(A_NORMAL);
04284 }
04285 tee_fprintf(stdout, _("Current pager:\t\t%s\n"), pager.c_str());
04286 tee_fprintf(stdout, _("Using outfile:\t\t'%s'\n"), opt_outfile ? outfile.c_str() : "");
04287 tee_fprintf(stdout, _("Using delimiter:\t%s\n"), delimiter);
04288 tee_fprintf(stdout, _("Server version:\t\t%s\n"), server_version_string(con));
04289 tee_fprintf(stdout, _("Protocol:\t\t%s\n"), opt_protocol.c_str());
04290 tee_fprintf(stdout, _("Protocol version:\t%d\n"), drizzle_con_protocol_version(con));
04291 tee_fprintf(stdout, _("Connection:\t\t%s\n"), drizzle_con_host(con));
04292
04293
04294
04295
04296
04297 if (drizzle_con_uds(con))
04298 {
04299 tee_fprintf(stdout, _("UNIX socket:\t\t%s\n"), drizzle_con_uds(con));
04300 }
04301 else
04302 {
04303 tee_fprintf(stdout, _("TCP port:\t\t%d\n"), drizzle_con_port(con));
04304 }
04305
04306 if (safe_updates)
04307 {
04308 vidattr(A_BOLD);
04309 tee_fprintf(stdout, _("\nNote that you are running in safe_update_mode:\n"));
04310 vidattr(A_NORMAL);
04311 tee_fprintf(stdout, _("\
04312 UPDATEs and DELETEs that don't use a key in the WHERE clause are not allowed.\n\
04313 (One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n \
04314 SELECT has an automatic 'LIMIT %lu' if LIMIT is not used.\n \
04315 Max number of examined row combination in a join is set to: %lu\n\n"),
04316 select_limit, max_join_size);
04317 }
04318 tee_puts("--------------\n", stdout);
04319 return 0;
04320 }
04321
04322 static const char *
04323 server_version_string(drizzle_con_st *local_con)
04324 {
04325 static string buf("");
04326 static bool server_version_string_reserved= false;
04327
04328 if (!server_version_string_reserved)
04329 {
04330 buf.reserve(MAX_SERVER_VERSION_LENGTH);
04331 server_version_string_reserved= true;
04332 }
04333
04334 if (buf[0] == '\0')
04335 {
04336 drizzle_result_st result;
04337 drizzle_return_t ret;
04338
04339 buf.append(drizzle_con_server_version(local_con));
04340
04341
04342 (void)drizzle_query_str(local_con, &result,
04343 "select @@version_comment limit 1", &ret);
04344 if (ret == DRIZZLE_RETURN_OK &&
04345 drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
04346 {
04347 drizzle_row_t cur = drizzle_row_next(&result);
04348 if (cur && cur[0])
04349 {
04350 buf.append(" ");
04351 buf.append(cur[0]);
04352 }
04353 drizzle_result_free(&result);
04354 }
04355 else if (ret == DRIZZLE_RETURN_ERROR_CODE)
04356 drizzle_result_free(&result);
04357 }
04358
04359 return buf.c_str();
04360 }
04361
04362 static int
04363 put_info(const char *str,INFO_TYPE info_type, uint32_t error, const char *sqlstate)
04364 {
04365 FILE *file= (info_type == INFO_ERROR ? stderr : stdout);
04366 static int inited=0;
04367
04368 if (status.getBatch())
04369 {
04370 if (info_type == INFO_ERROR)
04371 {
04372 (void) fflush(file);
04373 fprintf(file,_("ERROR"));
04374 if (error)
04375 {
04376 if (sqlstate)
04377 (void) fprintf(file," %d (%s)",error, sqlstate);
04378 else
04379 (void) fprintf(file," %d",error);
04380 }
04381 if (status.getQueryStartLine() && line_numbers)
04382 {
04383 (void) fprintf(file," at line %"PRIu32,status.getQueryStartLine());
04384 if (status.getFileName())
04385 (void) fprintf(file," in file: '%s'", status.getFileName());
04386 }
04387 (void) fprintf(file,": %s\n",str);
04388 (void) fflush(file);
04389 if (!ignore_errors)
04390 return 1;
04391 }
04392 else if (info_type == INFO_RESULT && verbose > 1)
04393 tee_puts(str, file);
04394 if (unbuffered)
04395 fflush(file);
04396 return info_type == INFO_ERROR ? -1 : 0;
04397 }
04398 if (!opt_silent || info_type == INFO_ERROR)
04399 {
04400 if (!inited)
04401 {
04402 inited=1;
04403 #ifdef HAVE_SETUPTERM
04404 (void) setupterm((char *)0, 1, (int *) 0);
04405 #endif
04406 }
04407 if (info_type == INFO_ERROR)
04408 {
04409 if (!opt_nobeep)
04410
04411 putchar('\a');
04412 vidattr(A_STANDOUT);
04413 if (error)
04414 {
04415 if (sqlstate)
04416 (void) tee_fprintf(file, _("ERROR %d (%s): "), error, sqlstate);
04417 else
04418 (void) tee_fprintf(file, _("ERROR %d: "), error);
04419 }
04420 else
04421 tee_puts(_("ERROR: "), file);
04422 }
04423 else
04424 vidattr(A_BOLD);
04425 (void) tee_puts(str, file);
04426 vidattr(A_NORMAL);
04427 }
04428 if (unbuffered)
04429 fflush(file);
04430 return info_type == INFO_ERROR ? -1 : 0;
04431 }
04432
04433
04434 static int
04435 put_error(drizzle_con_st *local_con, drizzle_result_st *res)
04436 {
04437 const char *error;
04438
04439 if (res != NULL)
04440 {
04441 error= drizzle_result_error(res);
04442 if (!strcmp(error, ""))
04443 {
04444 error= drizzle_con_error(local_con);
04445 }
04446 }
04447 else
04448 {
04449 error= drizzle_con_error(local_con);
04450 }
04451
04452 return put_info(error, INFO_ERROR,
04453 res == NULL ? drizzle_con_error_code(local_con) :
04454 drizzle_result_error_code(res),
04455 res == NULL ? drizzle_con_sqlstate(local_con) :
04456 drizzle_result_sqlstate(res));
04457 }
04458
04459
04460 static void remove_cntrl(string *buffer)
04461 {
04462 const char *start= buffer->c_str();
04463 const char *end= start + (buffer->length());
04464 while (start < end && !isgraph(end[-1]))
04465 end--;
04466 uint32_t pos_to_truncate= (end-start);
04467 if (buffer->length() > pos_to_truncate)
04468 buffer->erase(pos_to_truncate);
04469 }
04470
04471
04472 void tee_fprintf(FILE *file, const char *fmt, ...)
04473 {
04474 va_list args;
04475
04476 va_start(args, fmt);
04477 (void) vfprintf(file, fmt, args);
04478 va_end(args);
04479
04480 if (opt_outfile)
04481 {
04482 va_start(args, fmt);
04483 (void) vfprintf(OUTFILE, fmt, args);
04484 va_end(args);
04485 }
04486 }
04487
04488
04489 void tee_fputs(const char *s, FILE *file)
04490 {
04491 fputs(s, file);
04492 if (opt_outfile)
04493 fputs(s, OUTFILE);
04494 }
04495
04496
04497 void tee_puts(const char *s, FILE *file)
04498 {
04499 fputs(s, file);
04500 fputc('\n', file);
04501 if (opt_outfile)
04502 {
04503 fputs(s, OUTFILE);
04504 fputc('\n', OUTFILE);
04505 }
04506 }
04507
04508 void tee_putc(int c, FILE *file)
04509 {
04510 putc(c, file);
04511 if (opt_outfile)
04512 putc(c, OUTFILE);
04513 }
04514
04515 #include <sys/times.h>
04516
04517 static boost::posix_time::ptime start_timer(void)
04518 {
04519 return boost::posix_time::microsec_clock::universal_time();
04520 }
04521
04522 static void nice_time(boost::posix_time::time_duration duration, string &buff)
04523 {
04524 ostringstream tmp_buff_str;
04525
04526 if (duration.hours() > 0)
04527 {
04528 tmp_buff_str << duration.hours();
04529 if (duration.hours() > 1)
04530 tmp_buff_str << _(" hours ");
04531 else
04532 tmp_buff_str << _(" hour ");
04533 }
04534 if (duration.hours() > 0 || duration.minutes() > 0)
04535 {
04536 tmp_buff_str << duration.minutes() << _(" min ");
04537 }
04538
04539 tmp_buff_str.precision(duration.num_fractional_digits());
04540
04541 double seconds= duration.fractional_seconds();
04542
04543 seconds/= pow(10.0,duration.num_fractional_digits());
04544
04545 seconds+= duration.seconds();
04546 tmp_buff_str << seconds << _(" sec");
04547
04548 buff.append(tmp_buff_str.str());
04549 }
04550
04551 static void end_timer(boost::posix_time::ptime start_time, string &buff)
04552 {
04553 boost::posix_time::ptime end_time= start_timer();
04554 boost::posix_time::time_period duration(start_time, end_time);
04555
04556 nice_time(duration.length(), buff);
04557 }
04558
04559
04560 static void drizzle_end_timer(boost::posix_time::ptime start_time, string &buff)
04561 {
04562 buff.append(" (");
04563 end_timer(start_time,buff);
04564 buff.append(")");
04565 }
04566
04567 static const char * construct_prompt()
04568 {
04569
04570 assert(processed_prompt!=NULL);
04571 processed_prompt->clear();
04572
04573
04574 time_t lclock = time(NULL);
04575 struct tm *t = localtime(&lclock);
04576
04577
04578 string::iterator c= current_prompt.begin();
04579 while (c != current_prompt.end())
04580 {
04581 if (*c != PROMPT_CHAR)
04582 {
04583 processed_prompt->push_back(*c);
04584 }
04585 else
04586 {
04587 int getHour;
04588 int getYear;
04589
04590 char dateTime[32];
04591 switch (*++c) {
04592 case '\0':
04593
04594 --c;
04595 break;
04596 case 'c':
04597 add_int_to_prompt(++prompt_counter);
04598 break;
04599 case 'v':
04600 if (connected)
04601 processed_prompt->append(drizzle_con_server_version(con));
04602 else
04603 processed_prompt->append("not_connected");
04604 break;
04605 case 'd':
04606 processed_prompt->append(not current_db.empty() ? current_db : "(none)");
04607 break;
04608 case 'h':
04609 {
04610 const char *prompt= connected ? drizzle_con_host(con) : "not_connected";
04611 if (strstr(prompt, "Localhost"))
04612 processed_prompt->append("localhost");
04613 else
04614 {
04615 const char *end=strrchr(prompt,' ');
04616 if (end != NULL)
04617 processed_prompt->append(prompt, (end-prompt));
04618 }
04619 break;
04620 }
04621 case 'p':
04622 {
04623 if (!connected)
04624 {
04625 processed_prompt->append("not_connected");
04626 break;
04627 }
04628
04629 if (drizzle_con_uds(con))
04630 {
04631 const char *pos=strrchr(drizzle_con_uds(con),'/');
04632 processed_prompt->append(pos ? pos+1 : drizzle_con_uds(con));
04633 }
04634 else
04635 add_int_to_prompt(drizzle_con_port(con));
04636 }
04637 break;
04638 case 'U':
04639 if (!full_username)
04640 init_username();
04641 processed_prompt->append(full_username ? full_username :
04642 (!current_user.empty() ? current_user : "(unknown)"));
04643 break;
04644 case 'u':
04645 if (!full_username)
04646 init_username();
04647 processed_prompt->append(part_username ? part_username :
04648 (!current_user.empty() ? current_user : _("(unknown)")));
04649 break;
04650 case PROMPT_CHAR:
04651 {
04652 processed_prompt->append(PROMPT_CHAR, 1);
04653 }
04654 break;
04655 case 'n':
04656 {
04657 processed_prompt->append('\n', 1);
04658 }
04659 break;
04660 case ' ':
04661 case '_':
04662 {
04663 processed_prompt->append(' ', 1);
04664 }
04665 break;
04666 case 'R':
04667 if (t->tm_hour < 10)
04668 add_int_to_prompt(0);
04669 add_int_to_prompt(t->tm_hour);
04670 break;
04671 case 'r':
04672 getHour = t->tm_hour % 12;
04673 if (getHour == 0)
04674 getHour=12;
04675 if (getHour < 10)
04676 add_int_to_prompt(0);
04677 add_int_to_prompt(getHour);
04678 break;
04679 case 'm':
04680 if (t->tm_min < 10)
04681 add_int_to_prompt(0);
04682 add_int_to_prompt(t->tm_min);
04683 break;
04684 case 'y':
04685 getYear = t->tm_year % 100;
04686 if (getYear < 10)
04687 add_int_to_prompt(0);
04688 add_int_to_prompt(getYear);
04689 break;
04690 case 'Y':
04691 add_int_to_prompt(t->tm_year+1900);
04692 break;
04693 case 'D':
04694 strftime(dateTime, 32, "%a %b %d %H:%M:%S %Y", localtime(&lclock));
04695 processed_prompt->append(dateTime);
04696 break;
04697 case 's':
04698 if (t->tm_sec < 10)
04699 add_int_to_prompt(0);
04700 add_int_to_prompt(t->tm_sec);
04701 break;
04702 case 'w':
04703 processed_prompt->append(get_day_name(t->tm_wday));
04704 break;
04705 case 'P':
04706 processed_prompt->append(t->tm_hour < 12 ? "am" : "pm");
04707 break;
04708 case 'o':
04709 add_int_to_prompt(t->tm_mon+1);
04710 break;
04711 case 'O':
04712 processed_prompt->append(get_month_name(t->tm_mon));
04713 break;
04714 case '\'':
04715 processed_prompt->append("'");
04716 break;
04717 case '"':
04718 processed_prompt->append("\"");
04719 break;
04720 case 'S':
04721 processed_prompt->append(";");
04722 break;
04723 case 't':
04724 processed_prompt->append("\t");
04725 break;
04726 case 'l':
04727 processed_prompt->append(delimiter_str);
04728 break;
04729 default:
04730 processed_prompt->push_back(*c);
04731 }
04732 }
04733 ++c;
04734 }
04735 return processed_prompt->c_str();
04736 }
04737
04738
04739 static void add_int_to_prompt(int toadd)
04740 {
04741 ostringstream buffer;
04742 buffer << toadd;
04743 processed_prompt->append(buffer.str().c_str());
04744 }
04745
04746 static void init_username()
04747 {
04748
04749
04750
04751
04752
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762 }
04763
04764 static int com_prompt(string *, const char *line)
04765 {
04766 const char *ptr=strchr(line, ' ');
04767 if (ptr == NULL)
04768 tee_fprintf(stdout, _("Returning to default PROMPT of %s\n"),
04769 default_prompt);
04770 prompt_counter = 0;
04771 char * tmpptr= strdup(ptr ? ptr+1 : default_prompt);
04772 if (tmpptr == NULL)
04773 tee_fprintf(stdout, _("Memory allocation error. Not changing prompt\n"));
04774 else
04775 {
04776 current_prompt.erase();
04777 current_prompt= tmpptr;
04778 tee_fprintf(stdout, _("PROMPT set to '%s'\n"), current_prompt.c_str());
04779 }
04780 return 0;
04781 }
04782
04783
04784
04785
04786
04787
04788
04789 static const char * strcont(const char *str, const char *set)
04790 {
04791 const char * start = set;
04792
04793 while (*str)
04794 {
04795 while (*set)
04796 {
04797 if (*set++ == *str)
04798 return str;
04799 }
04800 set=start; str++;
04801 }
04802 return NULL;
04803 }