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