~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzle.cc

Moved the last of the libdrizzleclient calls into Protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 *
34
34
 **/
35
35
 
36
 
#include "config.h"
37
 
 
 
36
#include "client_priv.h"
38
37
#include <string>
39
 
 
40
 
#include "client_priv.h"
 
38
#include <algorithm>
41
39
#include <mystrings/m_ctype.h>
42
40
#include <stdarg.h>
43
 
#ifndef __GNU_LIBRARY__
44
 
#define __GNU_LIBRARY__          // Skip warnings in getopt.h
45
 
#endif
46
 
#include <readline/history.h>
47
41
#include "my_readline.h"
48
42
#include <signal.h>
49
43
#include <sys/ioctl.h>
50
 
 
51
 
 
52
 
#if defined(HAVE_LOCALE_H)
53
 
#include <locale.h>
54
 
#endif
55
 
 
56
 
#include <libdrizzle/gettext.h>
57
 
 
58
 
const char *VER= "14.14";
59
 
 
60
 
/* Don't try to make a nice table if the data is too big */
61
 
#define MAX_COLUMN_LENGTH       (uint32_t)1024
62
 
 
63
 
/* Buffer to hold 'version' and 'version_comment' */
64
 
#define MAX_SERVER_VERSION_LENGTH     128
65
 
 
66
 
/* Array of options to pass to libdrizzled */
67
 
#define MAX_SERVER_ARGS               64
68
 
 
69
 
void* sql_alloc(unsigned size);       // Don't use drizzled alloc for these
70
 
void sql_element_free(void *ptr);
71
 
 
 
44
#include <drizzled/configmake.h>
72
45
 
73
46
#if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
74
47
#include <curses.h>
99
72
#endif
100
73
#endif
101
74
 
102
 
#undef bcmp                             // Fix problem with new readline
103
 
 
104
 
#ifdef HAVE_READLINE_HISTORY_H
105
 
#include <readline/history.h>
106
 
#endif
107
 
#include <readline/readline.h>
 
75
#ifdef HAVE_LIBREADLINE
 
76
#  if defined(HAVE_READLINE_READLINE_H)
 
77
#    include <readline/readline.h>
 
78
#  elif defined(HAVE_READLINE_H)
 
79
#    include <readline.h>
 
80
#  else /* !defined(HAVE_READLINE_H) */
 
81
extern char *readline ();
 
82
#  endif /* !defined(HAVE_READLINE_H) */
 
83
char *cmdline = NULL;
 
84
#else /* !defined(HAVE_READLINE_READLINE_H) */
 
85
  /* no readline */
 
86
#  error Readline Required
 
87
#endif /* HAVE_LIBREADLINE */
 
88
 
 
89
#ifdef HAVE_READLINE_HISTORY
 
90
#  if defined(HAVE_READLINE_HISTORY_H)
 
91
#    include <readline/history.h>
 
92
#  elif defined(HAVE_HISTORY_H)
 
93
#    include <history.h>
 
94
#  else /* !defined(HAVE_HISTORY_H) */
 
95
extern void add_history ();
 
96
extern int write_history ();
 
97
extern int read_history ();
 
98
#  endif /* defined(HAVE_READLINE_HISTORY_H) */
 
99
    /* no history */
 
100
#endif /* HAVE_READLINE_HISTORY */
 
101
 
 
102
#define DRIZZLE_DEFAULT_INPUT_LINE 65536
108
103
 
109
104
/**
110
105
 Make the old readline interface look like the new one.
116
111
  completion_matches((char *)str, (CPFunction *)func)
117
112
#endif
118
113
 
 
114
#if defined(HAVE_LOCALE_H)
 
115
#include <locale.h>
 
116
#endif
 
117
 
 
118
#include <drizzled/gettext.h>
 
119
 
 
120
 
 
121
void* sql_alloc(unsigned size);       // Don't use drizzled alloc for these
 
122
void sql_element_free(void *ptr);
 
123
 
119
124
 
120
125
#if !defined(HAVE_VIDATTR)
121
126
#undef vidattr
122
127
#define vidattr(A) {}      // Can't get this to work
123
128
#endif
124
129
 
125
 
#ifdef FN_NO_CASE_SENCE
126
 
#define cmp_database(cs,A,B) my_strcasecmp((cs), (A), (B))
127
 
#else
128
 
#define cmp_database(cs,A,B) strcmp((A),(B))
129
 
#endif
130
 
 
131
 
#include "completion_hash.h"
 
130
#include <iostream>
 
131
#include <functional>
 
132
#include <map>
132
133
 
133
134
using namespace std;
134
135
 
 
136
const string VER("14.14");
 
137
/* Don't try to make a nice table if the data is too big */
 
138
const uint32_t MAX_COLUMN_LENGTH= 1024;
 
139
 
 
140
/* Buffer to hold 'version' and 'version_comment' */
 
141
const int MAX_SERVER_VERSION_LENGTH= 128;
 
142
 
135
143
#define PROMPT_CHAR '\\'
136
144
#define DEFAULT_DELIMITER ";"
137
145
 
145
153
} STATUS;
146
154
 
147
155
 
148
 
static HashTable ht;
 
156
static map<string, string>::iterator completion_iter;
 
157
static map<string, string>::iterator completion_end;
 
158
static map<string, string> completion_map;
 
159
static string completion_string;
 
160
 
149
161
static char **defaults_argv;
150
162
 
151
163
enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
152
164
typedef enum enum_info_type INFO_TYPE;
153
165
 
154
 
static DRIZZLE drizzle;      /* The connection */
155
 
static bool ignore_errors=0,quick=0,
156
 
  connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
157
 
  opt_rehash=1,skip_updates=0,safe_updates=0,one_database=0,
158
 
  opt_compress=0, using_opt_local_infile=0,
159
 
  vertical=0, line_numbers=1, column_names=1,
160
 
  opt_nopager=1, opt_outfile=0, named_cmds= 0,
161
 
  tty_password= 0, opt_nobeep=0, opt_reconnect=1,
162
 
  default_charset_used= 0, opt_secure_auth= 0,
163
 
  default_pager_set= 0, opt_sigint_ignore= 0,
164
 
  auto_vertical_output= 0,
165
 
  show_warnings= 0, executing_query= 0, interrupted_query= 0;
 
166
static drizzle_st drizzle;      /* The library handle */
 
167
static drizzle_con_st con;      /* The connection */
 
168
static bool ignore_errors= false, quick= false,
 
169
  connected= false, opt_raw_data= false, unbuffered= false,
 
170
  output_tables= false, opt_rehash= true, skip_updates= false,
 
171
  safe_updates= false, one_database= false,
 
172
  opt_compress= false,
 
173
  vertical= false, line_numbers= true, column_names= true,
 
174
  opt_nopager= true, opt_outfile= false, named_cmds= false,
 
175
  tty_password= false, opt_nobeep= false, opt_reconnect= true,
 
176
  default_charset_used= false, opt_secure_auth= false,
 
177
  default_pager_set= false, opt_sigint_ignore= false,
 
178
  auto_vertical_output= false,
 
179
  show_warnings= false, executing_query= false, interrupted_query= false;
 
180
static uint32_t  show_progress_size= 0;
166
181
static bool debug_info_flag, debug_check_flag;
167
182
static bool column_types_flag;
168
 
static bool preserve_comments= 0;
169
 
static uint32_t opt_max_allowed_packet, opt_net_buffer_length;
170
 
static int verbose=0,opt_silent=0,opt_drizzle_port=0, opt_local_infile=0;
171
 
static uint my_end_arg;
172
 
static char * opt_drizzle_unix_port=0;
173
 
static int connect_flag=CLIENT_INTERACTIVE;
174
 
static char *current_host,*current_db,*current_user=0,*opt_password=0,
175
 
  *delimiter_str= 0,* current_prompt= 0;
 
183
static bool preserve_comments= false;
 
184
static uint32_t opt_max_input_line, opt_drizzle_port= 0;
 
185
static int verbose= 0, opt_silent= 0, opt_local_infile= 0;
 
186
static uint32_t my_end_arg;
 
187
static char * opt_drizzle_unix_port= NULL;
 
188
static drizzle_capabilities_t connect_flag= DRIZZLE_CAPABILITIES_NONE;
 
189
static char *current_host, *current_db, *current_user= NULL,
 
190
  *opt_password= NULL, *delimiter_str= NULL, *current_prompt= NULL;
176
191
static char *histfile;
177
192
static char *histfile_tmp;
178
193
static string *glob_buffer;
179
194
static string *processed_prompt= NULL;
180
195
static char *default_prompt= NULL;
181
 
static char *full_username=0,*part_username=0;
 
196
static char *full_username= NULL,*part_username= NULL;
182
197
static STATUS status;
183
198
static uint32_t select_limit;
184
199
static uint32_t max_join_size;
185
200
static uint32_t opt_connect_timeout= 0;
186
 
static char drizzle_charsets_dir[FN_REFLEN+1];
187
201
// TODO: Need to i18n these
188
 
static const char *day_names[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
189
 
static const char *month_names[]={"Jan","Feb","Mar","Apr","May","Jun","Jul",
 
202
static const char *day_names[]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
 
203
static const char *month_names[]= {"Jan","Feb","Mar","Apr","May","Jun","Jul",
190
204
                                  "Aug","Sep","Oct","Nov","Dec"};
191
205
static char default_pager[FN_REFLEN];
192
206
static char pager[FN_REFLEN], outfile[FN_REFLEN];
193
207
static FILE *PAGER, *OUTFILE;
194
 
static MEM_ROOT hash_mem_root;
195
 
static uint prompt_counter;
 
208
static uint32_t prompt_counter;
196
209
static char delimiter[16]= DEFAULT_DELIMITER;
197
 
static uint delimiter_length= 1;
 
210
static uint32_t delimiter_length= 1;
198
211
unsigned short terminal_width= 80;
199
212
 
200
213
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
201
214
 
202
 
int drizzle_real_query_for_lazy(const char *buf, int length);
203
 
int drizzle_store_result_for_lazy(DRIZZLE_RES **result);
 
215
int drizzleclient_real_query_for_lazy(const char *buf, int length,
 
216
                                      drizzle_result_st *result,
 
217
                                      uint32_t *error_code);
 
218
int drizzleclient_store_result_for_lazy(drizzle_result_st *result);
204
219
 
205
220
 
206
221
void tee_fprintf(FILE *file, const char *fmt, ...);
210
225
static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
211
226
/* The names of functions that actually do the manipulation. */
212
227
static int get_options(int argc,char **argv);
213
 
bool get_one_option(int optid, const struct my_option *opt,
214
 
                    char *argument);
 
228
extern "C" bool get_one_option(int optid, const struct my_option *opt,
 
229
                               char *argument);
215
230
static int com_quit(string *str,const char*),
216
231
  com_go(string *str,const char*), com_ego(string *str,const char*),
217
232
  com_print(string *str,const char*),
226
241
 
227
242
static int read_and_execute(bool interactive);
228
243
static int sql_connect(char *host,char *database,char *user,char *password,
229
 
                       uint silent);
230
 
static const char *server_version_string(DRIZZLE *drizzle);
231
 
static int put_info(const char *str,INFO_TYPE info,uint error,
 
244
                       uint32_t silent);
 
245
static const char *server_version_string(drizzle_con_st *con);
 
246
static int put_info(const char *str,INFO_TYPE info,uint32_t error,
232
247
                    const char *sql_state);
233
 
static int put_error(DRIZZLE *drizzle);
 
248
static int put_error(drizzle_con_st *con, drizzle_result_st *res);
234
249
static void safe_put_field(const char *pos,uint32_t length);
235
250
static void init_pager(void);
236
251
static void end_pager(void);
240
255
static char *get_arg(char *line, bool get_next_arg);
241
256
static void init_username(void);
242
257
static void add_int_to_prompt(int toadd);
243
 
static int get_result_width(DRIZZLE_RES *res);
244
 
static int get_field_disp_length(DRIZZLE_FIELD * field);
 
258
static int get_result_width(drizzle_result_st *res);
 
259
static int get_field_disp_length(drizzle_column_st * field);
245
260
static const char * strcont(register const char *str, register const char *set);
246
261
 
247
262
/* A structure which contains information on the commands this program
256
271
 
257
272
 
258
273
static COMMANDS commands[] = {
259
 
  { "?",      '?', com_help,   1, N_("Synonym for `help'.") },
 
274
  { "?",      '?', com_help,   0, N_("Synonym for `help'.") },
260
275
  { "clear",  'c', com_clear,  0, N_("Clear command.")},
261
276
  { "connect",'r', com_connect,1,
262
277
    N_("Reconnect to the server. Optional arguments are db and host." }),
266
281
    N_("Send command to drizzle server, display result vertically.")},
267
282
  { "exit",   'q', com_quit,   0, N_("Exit drizzle. Same as quit.")},
268
283
  { "go",     'g', com_go,     0, N_("Send command to drizzle server.") },
269
 
  { "help",   'h', com_help,   1, N_("Display this help.") },
 
284
  { "help",   'h', com_help,   0, N_("Display this help.") },
270
285
  { "nopager",'n', com_nopager,0, N_("Disable pager, print to stdout.") },
271
286
  { "notee",  't', com_notee,  0, N_("Don't write into outfile.") },
272
287
  { "pager",  'P', com_pager,  1,
372
387
  { "CROSS", 0, 0, 0, ""},
373
388
  { "CUBE", 0, 0, 0, ""},
374
389
  { "CURRENT_DATE", 0, 0, 0, ""},
375
 
  { "CURRENT_TIME", 0, 0, 0, ""},
376
390
  { "CURRENT_TIMESTAMP", 0, 0, 0, ""},
377
391
  { "CURRENT_USER", 0, 0, 0, ""},
378
392
  { "CURSOR", 0, 0, 0, ""},
451
465
  { "FULL", 0, 0, 0, ""},
452
466
  { "FULLTEXT", 0, 0, 0, ""},
453
467
  { "FUNCTION", 0, 0, 0, ""},
454
 
  { "GET_FORMAT", 0, 0, 0, ""},
455
468
  { "GLOBAL", 0, 0, 0, ""},
456
469
  { "GRANT", 0, 0, 0, ""},
457
470
  { "GRANTS", 0, 0, 0, ""},
513
526
  { "LINESTRING", 0, 0, 0, ""},
514
527
  { "LOAD", 0, 0, 0, ""},
515
528
  { "LOCAL", 0, 0, 0, ""},
516
 
  { "LOCALTIME", 0, 0, 0, ""},
517
529
  { "LOCALTIMESTAMP", 0, 0, 0, ""},
518
530
  { "LOCK", 0, 0, 0, ""},
519
531
  { "LOCKS", 0, 0, 0, ""},
610
622
  { "QUARTER", 0, 0, 0, ""},
611
623
  { "QUERY", 0, 0, 0, ""},
612
624
  { "QUICK", 0, 0, 0, ""},
613
 
  { "RAID0", 0, 0, 0, ""},
614
 
  { "RAID_CHUNKS", 0, 0, 0, ""},
615
 
  { "RAID_CHUNKSIZE", 0, 0, 0, ""},
616
 
  { "RAID_TYPE", 0, 0, 0, ""},
617
625
  { "READ", 0, 0, 0, ""},
618
626
  { "READS", 0, 0, 0, ""},
619
627
  { "REAL", 0, 0, 0, ""},
715
723
  { "TERMINATED", 0, 0, 0, ""},
716
724
  { "TEXT", 0, 0, 0, ""},
717
725
  { "THEN", 0, 0, 0, ""},
718
 
  { "TIME", 0, 0, 0, ""},
719
726
  { "TIMESTAMP", 0, 0, 0, ""},
720
727
  { "TIMESTAMPADD", 0, 0, 0, ""},
721
728
  { "TIMESTAMPDIFF", 0, 0, 0, ""},
749
756
  { "USE_FRM", 0, 0, 0, ""},
750
757
  { "USING", 0, 0, 0, ""},
751
758
  { "UTC_DATE", 0, 0, 0, ""},
752
 
  { "UTC_TIME", 0, 0, 0, ""},
753
759
  { "UTC_TIMESTAMP", 0, 0, 0, ""},
754
760
  { "VALUE", 0, 0, 0, ""},
755
761
  { "VALUES", 0, 0, 0, ""},
776
782
  { "ABS", 0, 0, 0, ""},
777
783
  { "ACOS", 0, 0, 0, ""},
778
784
  { "ADDDATE", 0, 0, 0, ""},
779
 
  { "ADDTIME", 0, 0, 0, ""},
780
785
  { "AES_ENCRYPT", 0, 0, 0, ""},
781
786
  { "AES_DECRYPT", 0, 0, 0, ""},
782
787
  { "AREA", 0, 0, 0, ""},
814
819
  { "CRC32", 0, 0, 0, ""},
815
820
  { "CROSSES", 0, 0, 0, ""},
816
821
  { "CURDATE", 0, 0, 0, ""},
817
 
  { "CURTIME", 0, 0, 0, ""},
818
822
  { "DATE_ADD", 0, 0, 0, ""},
819
823
  { "DATEDIFF", 0, 0, 0, ""},
820
824
  { "DATE_FORMAT", 0, 0, 0, ""},
884
888
  { "LTRIM", 0, 0, 0, ""},
885
889
  { "MAKE_SET", 0, 0, 0, ""},
886
890
  { "MAKEDATE", 0, 0, 0, ""},
887
 
  { "MAKETIME", 0, 0, 0, ""},
888
891
  { "MASTER_POS_WAIT", 0, 0, 0, ""},
889
892
  { "MAX", 0, 0, 0, ""},
890
893
  { "MBRCONTAINS", 0, 0, 0, ""},
941
944
  { "ROW_COUNT", 0, 0, 0, ""},
942
945
  { "RPAD", 0, 0, 0, ""},
943
946
  { "RTRIM", 0, 0, 0, ""},
944
 
  { "SEC_TO_TIME", 0, 0, 0, ""},
945
947
  { "SESSION_USER", 0, 0, 0, ""},
946
948
  { "SUBDATE", 0, 0, 0, ""},
947
949
  { "SIGN", 0, 0, 0, ""},
963
965
  { "SUBSTR", 0, 0, 0, ""},
964
966
  { "SUBSTRING", 0, 0, 0, ""},
965
967
  { "SUBSTRING_INDEX", 0, 0, 0, ""},
966
 
  { "SUBTIME", 0, 0, 0, ""},
967
968
  { "SUM", 0, 0, 0, ""},
968
969
  { "SYSDATE", 0, 0, 0, ""},
969
970
  { "SYSTEM_USER", 0, 0, 0, ""},
970
971
  { "TAN", 0, 0, 0, ""},
971
972
  { "TIME_FORMAT", 0, 0, 0, ""},
972
 
  { "TIME_TO_SEC", 0, 0, 0, ""},
973
 
  { "TIMEDIFF", 0, 0, 0, ""},
974
973
  { "TO_DAYS", 0, 0, 0, ""},
975
974
  { "TOUCHES", 0, 0, 0, ""},
976
975
  { "TRIM", 0, 0, 0, ""},
1007
1006
static bool add_line(string *buffer,char *line,char *in_string,
1008
1007
                     bool *ml_comment);
1009
1008
static void remove_cntrl(string *buffer);
1010
 
static void print_table_data(DRIZZLE_RES *result);
1011
 
static void print_tab_data(DRIZZLE_RES *result);
1012
 
static void print_table_data_vertically(DRIZZLE_RES *result);
1013
 
static void print_warnings(void);
 
1009
static void print_table_data(drizzle_result_st *result);
 
1010
static void print_tab_data(drizzle_result_st *result);
 
1011
static void print_table_data_vertically(drizzle_result_st *result);
 
1012
static void print_warnings(uint32_t error_code);
1014
1013
static uint32_t start_timer(void);
1015
1014
static void end_timer(uint32_t start_time,char *buff);
1016
1015
static void drizzle_end_timer(uint32_t start_time,char *buff);
1017
1016
static void nice_time(double sec,char *buff,bool part_second);
1018
 
extern RETSIGTYPE drizzle_end(int sig);
1019
 
extern RETSIGTYPE handle_sigint(int sig);
 
1017
extern "C" void drizzle_end(int sig);
 
1018
extern "C" void handle_sigint(int sig);
1020
1019
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1021
 
static RETSIGTYPE window_resize(int sig);
 
1020
static void window_resize(int sig);
1022
1021
#endif
1023
1022
 
1024
1023
int main(int argc,char *argv[])
1035
1034
 
1036
1035
  MY_INIT(argv[0]);
1037
1036
  delimiter_str= delimiter;
1038
 
  default_prompt= my_strdup(getenv("DRIZZLE_PS1") ?
1039
 
                            getenv("DRIZZLE_PS1") :
1040
 
                            "drizzle>> ", MYF(0));
1041
 
  current_prompt= my_strdup(default_prompt, MYF(0));
 
1037
  default_prompt= strdup(getenv("DRIZZLE_PS1") ?
 
1038
                         getenv("DRIZZLE_PS1") :
 
1039
                         "drizzle> ");
 
1040
  
 
1041
  if (default_prompt == NULL)
 
1042
  {
 
1043
    fprintf(stderr, _("Memory allocation error while constructing initial "
 
1044
                      "prompt. Aborting.\n"));
 
1045
    exit(ENOMEM);
 
1046
  }
 
1047
  current_prompt= strdup(default_prompt);
 
1048
  if (current_prompt == NULL)
 
1049
  {
 
1050
    fprintf(stderr, _("Memory allocation error while constructing initial "
 
1051
                      "prompt. Aborting.\n"));
 
1052
    exit(ENOMEM);
 
1053
  }
1042
1054
  processed_prompt= new string();
1043
1055
  processed_prompt->reserve(32);
1044
1056
 
1045
1057
  prompt_counter=0;
1046
1058
 
1047
1059
  outfile[0]=0;      // no (default) outfile
1048
 
  my_stpcpy(pager, "stdout");  // the default, if --pager wasn't given
 
1060
  strcpy(pager, "stdout");  // the default, if --pager wasn't given
1049
1061
  {
1050
1062
    char *tmp=getenv("PAGER");
1051
1063
    if (tmp && strlen(tmp))
1052
1064
    {
1053
1065
      default_pager_set= 1;
1054
 
      my_stpcpy(default_pager, tmp);
 
1066
      strcpy(default_pager, tmp);
1055
1067
    }
1056
1068
  }
1057
1069
  if (!isatty(0) || !isatty(1))
1077
1089
      close(stdout_fileno_copy);             /* Clean up dup(). */
1078
1090
  }
1079
1091
 
1080
 
  load_defaults("my",load_default_groups,&argc,&argv);
 
1092
  load_defaults("drizzle",load_default_groups,&argc,&argv);
1081
1093
  defaults_argv=argv;
1082
1094
  if (get_options(argc, (char **) argv))
1083
1095
  {
1086
1098
    exit(1);
1087
1099
  }
1088
1100
  if (status.batch && !status.line_buff &&
1089
 
      !(status.line_buff=batch_readline_init(opt_max_allowed_packet+512,stdin)))
 
1101
      !(status.line_buff=batch_readline_init(opt_max_input_line+512,stdin)))
1090
1102
  {
1091
1103
    free_defaults(defaults_argv);
1092
1104
    my_end(0);
1093
1105
    exit(1);
1094
1106
  }
1095
 
  completion_hash_init(&ht, 128);
1096
 
  init_alloc_root(&hash_mem_root, 16384, 0);
1097
1107
  memset(&drizzle, 0, sizeof(drizzle));
1098
1108
  if (sql_connect(current_host,current_db,current_user,opt_password,
1099
1109
                  opt_silent))
1123
1133
 
1124
1134
  glob_buffer= new string();
1125
1135
  glob_buffer->reserve(512);
1126
 
  
 
1136
 
1127
1137
  char * output_buff= (char *)malloc(512);
1128
1138
  memset(output_buff, '\0', 512);
1129
1139
 
1130
1140
  sprintf(output_buff,
1131
1141
          _("Your Drizzle connection id is %u\nServer version: %s\n"),
1132
 
          drizzle_thread_id(&drizzle),
1133
 
          server_version_string(&drizzle));
 
1142
          drizzle_con_thread_id(&con),
 
1143
          server_version_string(&con));
1134
1144
  put_info(output_buff, INFO_INFO, 0, 0);
1135
1145
 
1136
1146
  initialize_readline(current_prompt);
1141
1151
      histfile= strdup(getenv("DRIZZLE_HISTFILE"));
1142
1152
    else if (getenv("HOME"))
1143
1153
    {
1144
 
      histfile=(char*) my_malloc((uint) strlen(getenv("HOME"))
1145
 
                                 + (uint) strlen("/.drizzle_history")+2,
1146
 
                                 MYF(MY_WME));
 
1154
      histfile=(char*) malloc(strlen(getenv("HOME")) + strlen("/.drizzle_history") + 2);
1147
1155
      if (histfile)
1148
1156
        sprintf(histfile,"%s/.drizzle_history",getenv("HOME"));
1149
1157
      char link_name[FN_REFLEN];
1160
1168
      if (verbose)
1161
1169
        tee_fprintf(stdout, _("Reading history-file %s\n"),histfile);
1162
1170
      read_history(histfile);
1163
 
      if (!(histfile_tmp= (char*) my_malloc((uint) strlen(histfile) + 5,
1164
 
                                            MYF(MY_WME))))
 
1171
      if (!(histfile_tmp= (char*) malloc((uint32_t) strlen(histfile) + 5)))
1165
1172
      {
1166
1173
        fprintf(stderr, _("Couldn't allocate memory for temp histfile!\n"));
1167
1174
        exit(1);
1181
1188
  return(0);        // Keep compiler happy
1182
1189
}
1183
1190
 
1184
 
RETSIGTYPE drizzle_end(int sig)
 
1191
void drizzle_end(int sig)
1185
1192
{
1186
 
  drizzle_close(&drizzle);
 
1193
  drizzle_con_free(&con);
 
1194
  drizzle_free(&drizzle);
1187
1195
  if (!status.batch && !quick && histfile)
1188
1196
  {
1189
1197
    /* write-history */
1193
1201
      my_rename(histfile_tmp, histfile, MYF(MY_WME));
1194
1202
  }
1195
1203
  batch_readline_end(status.line_buff);
1196
 
  completion_hash_free(&ht);
1197
 
  free_root(&hash_mem_root,MYF(0));
1198
1204
 
1199
1205
  if (sig >= 0)
1200
1206
    put_info(sig ? _("Aborted") : _("Bye"), INFO_RESULT,0,0);
1224
1230
  If query is in process, kill query
1225
1231
  no query in process, terminate like previous behavior
1226
1232
*/
1227
 
RETSIGTYPE handle_sigint(int sig)
 
1233
extern "C"
 
1234
void handle_sigint(int sig)
1228
1235
{
1229
1236
  char kill_buffer[40];
1230
 
  DRIZZLE *kill_drizzle= NULL;
 
1237
  drizzle_con_st kill_drizzle;
 
1238
  drizzle_result_st res;
 
1239
  drizzle_return_t ret;
1231
1240
 
1232
1241
  /* terminate if no query being executed, or we already tried interrupting */
1233
1242
  if (!executing_query || interrupted_query) {
1234
1243
    goto err;
1235
1244
  }
1236
1245
 
1237
 
  kill_drizzle= drizzle_create(kill_drizzle);
1238
 
  if (!drizzle_connect(kill_drizzle,current_host, current_user, opt_password,
1239
 
                          "", opt_drizzle_port, opt_drizzle_unix_port,0))
 
1246
  if (drizzle_con_add_tcp(&drizzle, &kill_drizzle, current_host,
 
1247
                          opt_drizzle_port, current_user, opt_password, NULL,
 
1248
                          DRIZZLE_CON_NONE) == NULL)
1240
1249
  {
1241
1250
    goto err;
1242
1251
  }
1243
1252
 
1244
1253
  /* kill_buffer is always big enough because max length of %lu is 15 */
1245
 
  sprintf(kill_buffer, "KILL /*!50000 QUERY */ %u", drizzle_thread_id(&drizzle));
1246
 
  drizzle_real_query(kill_drizzle, kill_buffer, strlen(kill_buffer));
1247
 
  drizzle_close(kill_drizzle);
 
1254
  sprintf(kill_buffer, "KILL /*!50000 QUERY */ %u",
 
1255
          drizzle_con_thread_id(&con));
 
1256
 
 
1257
  if (drizzle_query_str(&kill_drizzle, &res, kill_buffer, &ret) != NULL)
 
1258
    drizzle_result_free(&res);
 
1259
 
 
1260
  drizzle_con_free(&kill_drizzle);
1248
1261
  tee_fprintf(stdout, _("Query aborted by Ctrl+C\n"));
1249
1262
 
1250
1263
  interrupted_query= 1;
1257
1270
 
1258
1271
 
1259
1272
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1260
 
RETSIGTYPE window_resize(int sig __attribute__((unused)))
 
1273
void window_resize(int)
1261
1274
{
1262
1275
  struct winsize window_size;
1263
1276
 
1277
1290
   (char**) &opt_rehash, (char**) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
1278
1291
   0, 0},
1279
1292
  {"no-auto-rehash", 'A',
1280
 
   N_("No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of DRIZZLE and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead."),
 
1293
   N_("No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of drizzle_st and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead."),
1281
1294
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1282
1295
  {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
1283
1296
   N_("Automatically switch to vertical output mode if the result is wider than the terminal width."),
1284
1297
   (char**) &auto_vertical_output, (char**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1285
1298
  {"batch", 'B',
1286
1299
   N_("Don't use history file. Disable interactive behavior. (Enables --silent)"), 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1287
 
  {"character-sets-dir", OPT_CHARSETS_DIR,
1288
 
   N_("Directory where character sets are."), (char**) &charsets_dir,
1289
 
   (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1290
1300
  {"column-type-info", OPT_COLUMN_TYPES, N_("Display column type information."),
1291
1301
   (char**) &column_types_flag, (char**) &column_types_flag,
1292
1302
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1360
1370
  {"no-pager", OPT_NOPAGER,
1361
1371
   N_("Disable pager and print to stdout. See interactive help (\\h) also. WARNING: option deprecated; use --disable-pager instead."),
1362
1372
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1363
 
  {"password", 'p',
 
1373
  {"password", 'P',
1364
1374
   N_("Password to use when connecting to server. If password is not given it's asked from the tty."),
1365
1375
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1366
 
  {"port", 'P', N_("Port number to use for connection or 0 for default to, in order of preference, my.cnf, $DRIZZLE_TCP_PORT, ")
 
1376
  {"port", 'p', N_("Port number to use for connection or 0 for default to, in order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, ")
1367
1377
   N_("built-in default") " (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
1368
 
   (char**) &opt_drizzle_port,
1369
 
   (char**) &opt_drizzle_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,  0},
 
1378
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1370
1379
  {"prompt", OPT_PROMPT, N_("Set the drizzle prompt to this value."),
1371
1380
   (char**) &current_prompt, (char**) &current_prompt, 0, GET_STR_ALLOC,
1372
1381
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1373
 
  {"protocol", OPT_DRIZZLE_PROTOCOL, N_("The protocol of connection (tcp,socket,pipe,memory)."),
1374
 
   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1375
1382
  {"quick", 'q',
1376
1383
   N_("Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file."),
1377
1384
   (char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1411
1418
  {"connect_timeout", OPT_CONNECT_TIMEOUT,
1412
1419
   N_("Number of seconds before connection timeout."),
1413
1420
   (char**) &opt_connect_timeout,
1414
 
   (char**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0,
 
1421
   (char**) &opt_connect_timeout, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 3600*12, 0,
1415
1422
   0, 0},
1416
 
  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
1417
 
   N_("Max packet length to send to, or receive from server"),
1418
 
   (char**) &opt_max_allowed_packet, (char**) &opt_max_allowed_packet, 0,
1419
 
   GET_ULONG, REQUIRED_ARG, 16 *1024L*1024L, 4096,
 
1423
  {"max_input_line", OPT_MAX_INPUT_LINE,
 
1424
   N_("Max length of input line"),
 
1425
   (char**) &opt_max_input_line, (char**) &opt_max_input_line, 0,
 
1426
   GET_UINT32, REQUIRED_ARG, 16 *1024L*1024L, 4096,
1420
1427
   (int64_t) 2*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
1421
 
  {"net_buffer_length", OPT_NET_BUFFER_LENGTH,
1422
 
   N_("Buffer for TCP/IP and socket communication"),
1423
 
   (char**) &opt_net_buffer_length, (char**) &opt_net_buffer_length, 0, GET_ULONG,
1424
 
   REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0},
1425
1428
  {"select_limit", OPT_SELECT_LIMIT,
1426
1429
   N_("Automatic limit for SELECT when using --safe-updates"),
1427
1430
   (char**) &select_limit,
1428
 
   (char**) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ULONG_MAX,
 
1431
   (char**) &select_limit, 0, GET_UINT32, REQUIRED_ARG, 1000L, 1, ULONG_MAX,
1429
1432
   0, 1, 0},
1430
1433
  {"max_join_size", OPT_MAX_JOIN_SIZE,
1431
1434
   N_("Automatic limit for rows in a join when using --safe-updates"),
1432
1435
   (char**) &max_join_size,
1433
 
   (char**) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ULONG_MAX,
 
1436
   (char**) &max_join_size, 0, GET_UINT32, REQUIRED_ARG, 1000000L, 1, ULONG_MAX,
1434
1437
   0, 1, 0},
1435
1438
  {"secure-auth", OPT_SECURE_AUTH, N_("Refuse client connecting to server if it uses old (pre-4.1.1) protocol"), (char**) &opt_secure_auth,
1436
1439
   (char**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1437
1440
  {"show-warnings", OPT_SHOW_WARNINGS, N_("Show warnings after every statement."),
1438
1441
   (char**) &show_warnings, (char**) &show_warnings, 0, GET_BOOL, NO_ARG,
1439
1442
   0, 0, 0, 0, 0, 0},
 
1443
  {"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of lines before each import progress report."),
 
1444
   (char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
 
1445
   0, 0, 0, 0, 0, 0},
1440
1446
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1441
1447
};
1442
1448
 
1446
1452
  const char* readline= "readline";
1447
1453
 
1448
1454
  printf(_("%s  Ver %s Distrib %s, for %s (%s) using %s %s\n"),
1449
 
         my_progname, VER, drizzle_get_client_info(),
 
1455
         my_progname, VER.c_str(), drizzle_version(),
1450
1456
         SYSTEM_TYPE, MACHINE_TYPE,
1451
1457
         readline, rl_library_version);
1452
1458
 
1453
1459
  if (version)
1454
1460
    return;
1455
 
  printf(_("\
1456
 
Copyright (C) 2000-2008 MySQL AB\n                                      \
1457
 
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n \
1458
 
and you are welcome to modify and redistribute it under the GPL license\n"));
 
1461
  printf(_("Copyright (C) 2008 Sun Microsystems\n"
 
1462
           "This software comes with ABSOLUTELY NO WARRANTY. "
 
1463
           "This is free software,\n"
 
1464
           "and you are welcome to modify and redistribute it "
 
1465
           "under the GPL license\n"));
1459
1466
  printf(_("Usage: %s [OPTIONS] [database]\n"), my_progname);
1460
1467
  my_print_help(my_long_options);
1461
 
  print_defaults("my", load_default_groups);
 
1468
  print_defaults("drizzle", load_default_groups);
1462
1469
  my_print_variables(my_long_options);
1463
1470
}
1464
1471
 
1465
1472
 
1466
 
bool
1467
 
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1468
 
               char *argument)
 
1473
extern "C" bool
 
1474
get_one_option(int optid, const struct my_option *, char *argument)
1469
1475
{
 
1476
  char *endchar= NULL;
 
1477
  uint64_t temp_drizzle_port= 0;
 
1478
 
1470
1479
  switch(optid) {
1471
 
  case OPT_CHARSETS_DIR:
1472
 
    strmake(drizzle_charsets_dir, argument, sizeof(drizzle_charsets_dir) - 1);
1473
 
    charsets_dir = drizzle_charsets_dir;
1474
 
    break;
1475
1480
  case  OPT_DEFAULT_CHARSET:
1476
1481
    default_charset_used= 1;
1477
1482
    break;
1478
1483
  case OPT_DELIMITER:
1479
1484
    if (argument == disabled_my_option)
1480
1485
    {
1481
 
      my_stpcpy(delimiter, DEFAULT_DELIMITER);
 
1486
      strcpy(delimiter, DEFAULT_DELIMITER);
1482
1487
    }
1483
1488
    else
1484
1489
    {
1485
1490
      /* Check that delimiter does not contain a backslash */
1486
1491
      if (!strstr(argument, "\\"))
1487
1492
      {
1488
 
        strmake(delimiter, argument, sizeof(delimiter) - 1);
 
1493
        strncpy(delimiter, argument, sizeof(delimiter) - 1);
1489
1494
      }
1490
1495
      else
1491
1496
      {
1492
1497
        put_info(_("DELIMITER cannot contain a backslash character"),
1493
1498
                 INFO_ERROR,0,0);
1494
 
        return 0;
 
1499
        return false;
1495
1500
      }
1496
1501
    }
1497
 
    delimiter_length= (uint)strlen(delimiter);
 
1502
    delimiter_length= (uint32_t)strlen(delimiter);
1498
1503
    delimiter_str= delimiter;
1499
1504
    break;
1500
 
  case OPT_LOCAL_INFILE:
1501
 
    using_opt_local_infile=1;
1502
 
    break;
1503
1505
  case OPT_TEE:
1504
1506
    if (argument == disabled_my_option)
1505
1507
    {
1523
1525
      if (argument && strlen(argument))
1524
1526
      {
1525
1527
        default_pager_set= 1;
1526
 
        strmake(pager, argument, sizeof(pager) - 1);
1527
 
        my_stpcpy(default_pager, pager);
 
1528
        strncpy(pager, argument, sizeof(pager) - 1);
 
1529
        strcpy(default_pager, pager);
1528
1530
      }
1529
1531
      else if (default_pager_set)
1530
 
        my_stpcpy(pager, default_pager);
 
1532
        strcpy(pager, default_pager);
1531
1533
      else
1532
1534
        opt_nopager= 1;
1533
1535
    }
1560
1562
      one_database= skip_updates= 1;
1561
1563
    break;
1562
1564
  case 'p':
 
1565
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
 
1566
    /* if there is an alpha character this is not a valid port */
 
1567
    if (strlen(endchar) != 0)
 
1568
    {
 
1569
      put_info(_("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead."), INFO_ERROR, 0, 0);
 
1570
      return false;
 
1571
    }
 
1572
    /* If the port number is > 65535 it is not a valid port
 
1573
       This also helps with potential data loss casting unsigned long to a
 
1574
       uint32_t. */
 
1575
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
1576
    {
 
1577
      put_info(_("Value supplied for port is not valid."), INFO_ERROR, 0, 0);
 
1578
      return false;
 
1579
    }
 
1580
    else
 
1581
    {
 
1582
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
 
1583
    }
 
1584
    break;
 
1585
  case 'P':
 
1586
    /* Don't require password */
1563
1587
    if (argument == disabled_my_option)
1564
 
      argument= (char*) "";      // Don't require password
 
1588
    {
 
1589
      argument= (char*) "";
 
1590
    }
1565
1591
    if (argument)
1566
1592
    {
1567
1593
      char *start= argument;
1568
1594
      free(opt_password);
1569
1595
      opt_password= strdup(argument);
1570
 
      while (*argument) *argument++= 'x';        // Destroy argument
 
1596
      while (*argument)
 
1597
      {
 
1598
        /* Overwriting password with 'x' */
 
1599
        *argument++= 'x';
 
1600
      }
1571
1601
      if (*start)
1572
 
        start[1]=0 ;
 
1602
      {
 
1603
        start[1]= 0;
 
1604
      }
1573
1605
      tty_password= 0;
1574
1606
    }
1575
1607
    else
 
1608
    {
1576
1609
      tty_password= 1;
 
1610
    }
1577
1611
    break;
1578
1612
  case 's':
1579
1613
    if (argument == disabled_my_option)
1592
1626
    status.add_to_history= 0;
1593
1627
    set_if_bigger(opt_silent,1);                         // more silent
1594
1628
    break;
1595
 
    break;
1596
1629
  case 'V':
1597
1630
    usage(1);
1598
1631
    exit(0);
1609
1642
{
1610
1643
  char *tmp, *pagpoint;
1611
1644
  int ho_error;
1612
 
  const DRIZZLE_PARAMETERS *drizzle_params= drizzle_get_parameters();
1613
1645
 
1614
1646
  tmp= (char *) getenv("DRIZZLE_HOST");
1615
1647
  if (tmp)
1618
1650
  pagpoint= getenv("PAGER");
1619
1651
  if (!((char*) (pagpoint)))
1620
1652
  {
1621
 
    my_stpcpy(pager, "stdout");
 
1653
    strcpy(pager, "stdout");
1622
1654
    opt_nopager= 1;
1623
1655
  }
1624
1656
  else
1625
 
    my_stpcpy(pager, pagpoint);
1626
 
  my_stpcpy(default_pager, pager);
1627
 
 
1628
 
  opt_max_allowed_packet= *drizzle_params->p_max_allowed_packet;
1629
 
  opt_net_buffer_length= *drizzle_params->p_net_buffer_length;
 
1657
    strcpy(pager, pagpoint);
 
1658
  strcpy(default_pager, pager);
1630
1659
 
1631
1660
  if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
1632
1661
    exit(ho_error);
1633
1662
 
1634
 
  *drizzle_params->p_max_allowed_packet= opt_max_allowed_packet;
1635
 
  *drizzle_params->p_net_buffer_length= opt_net_buffer_length;
1636
 
 
1637
1663
  if (status.batch) /* disable pager and outfile in this case */
1638
1664
  {
1639
 
    my_stpcpy(default_pager, "stdout");
1640
 
    my_stpcpy(pager, "stdout");
 
1665
    strcpy(default_pager, "stdout");
 
1666
    strcpy(pager, "stdout");
1641
1667
    opt_nopager= 1;
1642
1668
    default_pager_set= 0;
1643
1669
    opt_outfile= 0;
1644
1670
    opt_reconnect= 0;
1645
 
    connect_flag= 0; /* Not in interactive mode */
 
1671
    connect_flag= DRIZZLE_CAPABILITIES_NONE; /* Not in interactive mode */
1646
1672
  }
1647
1673
 
1648
1674
  if (argc > 1)
1657
1683
    current_db= strdup(*argv);
1658
1684
  }
1659
1685
  if (tty_password)
1660
 
    opt_password= get_tty_password(NULL);
 
1686
    opt_password= client_get_tty_password(NULL);
1661
1687
  if (debug_info_flag)
1662
1688
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1663
1689
  if (debug_check_flag)
1691
1717
          (unsigned char) line[2] == 0xBF)
1692
1718
        line+= 3;
1693
1719
      line_number++;
 
1720
      if (show_progress_size > 0)
 
1721
      {
 
1722
        if ((line_number % show_progress_size) == 0)
 
1723
          fprintf(stderr, _("Processing line: %"PRIu32"\n"), line_number);
 
1724
      }
1694
1725
      if (!glob_buffer->empty())
1695
1726
        status.query_start_line=line_number;
1696
1727
    }
1762
1793
 
1763
1794
static COMMANDS *find_command(const char *name,char cmd_char)
1764
1795
{
1765
 
  uint len;
 
1796
  uint32_t len;
1766
1797
  const char *end;
1767
1798
 
1768
1799
  if (!name)
1788
1819
      return((COMMANDS *) 0);
1789
1820
    if ((end=strcont(name," \t")))
1790
1821
    {
1791
 
      len=(uint) (end - name);
 
1822
      len=(uint32_t) (end - name);
1792
1823
      while (my_isspace(charset_info,*end))
1793
1824
        end++;
1794
1825
      if (!*end)
1795
1826
        end=0;          // no arguments to function
1796
1827
    }
1797
1828
    else
1798
 
      len=(uint) strlen(name);
 
1829
      len=(uint32_t) strlen(name);
1799
1830
  }
1800
1831
 
1801
 
  for (uint i= 0; commands[i].name; i++)
 
1832
  for (uint32_t i= 0; commands[i].name; i++)
1802
1833
  {
1803
1834
    if (commands[i].func &&
1804
1835
        ((name && !my_strnncoll(charset_info,(const unsigned char*)name,len, (const unsigned char*)commands[i].name,len) && !commands[i].name[len] && (!end || (end && commands[i].takes_params))) || (!name && commands[i].cmd_char == cmd_char)))
1824
1855
    return(0);
1825
1856
  if (status.add_to_history && line[0] && not_in_history(line))
1826
1857
    add_history(line);
1827
 
  char *end_of_line=line+(uint) strlen(line);
 
1858
  char *end_of_line=line+(uint32_t) strlen(line);
1828
1859
 
1829
1860
  for (pos=out=line ; (inchar= (unsigned char) *pos) ; pos++)
1830
1861
  {
1854
1885
    }
1855
1886
#endif
1856
1887
        if (!*ml_comment && inchar == '\\' &&
1857
 
            !(*in_string && (drizzle.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)))
 
1888
            !(*in_string && (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_NO_BACKSLASH_ESCAPES)))
1858
1889
    {
1859
1890
      // Found possbile one character command like \c
1860
1891
 
2068
2099
  if (out != line || (buffer->length() > 0))
2069
2100
  {
2070
2101
    *out++='\n';
2071
 
    uint length=(uint) (out-line);
 
2102
    uint32_t length=(uint32_t) (out-line);
2072
2103
    if ((!*ml_comment || preserve_comments))
2073
2104
      buffer->append(line, length);
2074
2105
  }
2081
2112
 
2082
2113
 
2083
2114
static char **mysql_completion (const char *text, int start, int end);
2084
 
static char *new_command_generator(const char *text, int);
 
2115
extern "C" char *new_command_generator(const char *text, int);
2085
2116
 
2086
2117
/*
2087
2118
  Tell the GNU Readline library how to complete.  We want to try to complete
2088
2119
  on command names if this is the first word in the line, or on filenames
2089
2120
  if not.
2090
2121
*/
2091
 
static char *no_completion(const char * a __attribute__((unused)),
2092
 
                           int b __attribute__((unused)))
 
2122
static char *no_completion(const char *, int)
2093
2123
{
2094
2124
  /* No filename completion */
2095
2125
  return 0;
2184
2214
  entire line in case we want to do some simple parsing.  Return the
2185
2215
  array of matches, or NULL if there aren't any.
2186
2216
*/
2187
 
char **mysql_completion (const char *text,
2188
 
                        int start __attribute__((unused)),
2189
 
                        int end __attribute__((unused)))
 
2217
char **mysql_completion (const char *text, int, int)
2190
2218
{
2191
2219
  if (!status.batch && !quick)
2192
2220
    return rl_completion_matches(text, new_command_generator);
2194
2222
    return (char**) 0;
2195
2223
}
2196
2224
 
2197
 
 
2198
 
static char *new_command_generator(const char *text,int state)
2199
 
{
2200
 
  static int textlen;
2201
 
  char *ptr;
2202
 
  static Bucket *b;
2203
 
  static entry *e;
2204
 
  static uint i;
 
2225
inline string lower_string(const string &from_string)
 
2226
{
 
2227
  string to_string= from_string;
 
2228
  transform(to_string.begin(), to_string.end(),
 
2229
            to_string.begin(), ::tolower);
 
2230
  return to_string;
 
2231
}
 
2232
inline string lower_string(const char * from_string)
 
2233
{
 
2234
  string to_string= from_string;
 
2235
  return lower_string(to_string);
 
2236
}
 
2237
 
 
2238
template <class T>
 
2239
class CompletionMatch :
 
2240
  public unary_function<const string&, bool>
 
2241
{
 
2242
  string match_text; 
 
2243
  T match_func;
 
2244
public:
 
2245
  CompletionMatch(string text) : match_text(text) {}
 
2246
  inline bool operator() (const pair<string,string> &match_against) const
 
2247
  {
 
2248
    string sub_match=
 
2249
      lower_string(match_against.first.substr(0,match_text.size()));
 
2250
    return match_func(sub_match,match_text);
 
2251
  }
 
2252
};
 
2253
 
 
2254
 
 
2255
 
 
2256
extern "C"
 
2257
char *new_command_generator(const char *text, int state)
 
2258
{
2205
2259
 
2206
2260
  if (!state)
2207
 
    textlen=(uint) strlen(text);
2208
 
 
2209
 
  if (textlen>0)
2210
 
  {            /* lookup in the hash */
2211
 
    if (!state)
2212
 
    {
2213
 
      uint len;
2214
 
 
2215
 
      b = find_all_matches(&ht,text,(uint) strlen(text),&len);
2216
 
      if (!b)
2217
 
        return NULL;
2218
 
      e = b->pData;
2219
 
    }
2220
 
 
2221
 
    if (e)
2222
 
    {
2223
 
      ptr= strdup(e->str);
2224
 
      e = e->pNext;
2225
 
      return ptr;
2226
 
    }
2227
 
  }
2228
 
  else
2229
 
  { /* traverse the entire hash, ugly but works */
2230
 
 
2231
 
    if (!state)
2232
 
    {
2233
 
      /* find the first used bucket */
2234
 
      for (i=0 ; i < ht.nTableSize ; i++)
2235
 
      {
2236
 
        if (ht.arBuckets[i])
2237
 
        {
2238
 
          b = ht.arBuckets[i];
2239
 
          e = b->pData;
2240
 
          break;
2241
 
        }
2242
 
      }
2243
 
    }
2244
 
    ptr= NULL;
2245
 
    while (e && !ptr)
2246
 
    {          /* find valid entry in bucket */
2247
 
      if ((uint) strlen(e->str) == b->nKeyLength)
2248
 
        ptr = strdup(e->str);
2249
 
      /* find the next used entry */
2250
 
      e = e->pNext;
2251
 
      if (!e)
2252
 
      { /* find the next used bucket */
2253
 
        b = b->pNext;
2254
 
        if (!b)
2255
 
        {
2256
 
          for (i++ ; i<ht.nTableSize; i++)
2257
 
          {
2258
 
            if (ht.arBuckets[i])
2259
 
            {
2260
 
              b = ht.arBuckets[i];
2261
 
              e = b->pData;
2262
 
              break;
2263
 
            }
2264
 
          }
2265
 
        }
2266
 
        else
2267
 
          e = b->pData;
2268
 
      }
2269
 
    }
2270
 
    if (ptr)
2271
 
      return ptr;
2272
 
  }
2273
 
  return NULL;
 
2261
  {
 
2262
    completion_string= lower_string(text);
 
2263
    if (completion_string.size() == 0)
 
2264
    {
 
2265
      completion_iter= completion_map.begin();
 
2266
      completion_end= completion_map.end();
 
2267
    }
 
2268
    else
 
2269
    {
 
2270
      completion_iter= find_if(completion_map.begin(), completion_map.end(),
 
2271
                               CompletionMatch<equal_to<string> >(completion_string));
 
2272
      completion_end= find_if(completion_iter, completion_map.end(),
 
2273
                              CompletionMatch<not_equal_to<string> >(completion_string));
 
2274
    }
 
2275
  }
 
2276
  if (completion_iter == completion_end || (size_t)state > completion_map.size())
 
2277
    return NULL;
 
2278
  char *result= (char *)malloc((*completion_iter).second.size()+1);
 
2279
  strcpy(result, (*completion_iter).second.c_str());
 
2280
  completion_iter++;
 
2281
  return result;
2274
2282
}
2275
2283
 
2276
 
 
2277
2284
/* Build up the completion hash */
2278
2285
 
2279
2286
static void build_completion_hash(bool rehash, bool write_info)
2280
2287
{
2281
2288
  COMMANDS *cmd=commands;
2282
 
  DRIZZLE_RES *databases=0,*tables=0;
2283
 
  DRIZZLE_RES *fields;
2284
 
  static char ***field_names= 0;
2285
 
  DRIZZLE_ROW database_row,table_row;
2286
 
  DRIZZLE_FIELD *sql_field;
2287
 
  char buf[NAME_LEN*2+2];     // table name plus field name plus 2
2288
 
  int i,j,num_fields;
2289
 
 
 
2289
  drizzle_return_t ret;
 
2290
  drizzle_result_st databases,tables,fields;
 
2291
  drizzle_row_t database_row,table_row;
 
2292
  drizzle_column_st *sql_field;
 
2293
  string tmp_str, tmp_str_lower;
2290
2294
 
2291
2295
  if (status.batch || quick || !current_db)
2292
2296
    return;      // We don't need completion in batches
2293
2297
  if (!rehash)
2294
2298
    return;
2295
2299
 
2296
 
  /* Free old used memory */
2297
 
  if (field_names)
2298
 
    field_names=0;
2299
 
  completion_hash_clean(&ht);
2300
 
  free_root(&hash_mem_root,MYF(0));
 
2300
  completion_map.clear();
2301
2301
 
2302
2302
  /* hash this file's known subset of SQL commands */
2303
2303
  while (cmd->name) {
2304
 
    add_word(&ht,(char*) cmd->name);
 
2304
    tmp_str= cmd->name;
 
2305
    tmp_str_lower= lower_string(tmp_str);
 
2306
    completion_map[tmp_str_lower]= tmp_str;
2305
2307
    cmd++;
2306
2308
  }
2307
2309
 
2308
2310
  /* hash Drizzle functions (to be implemented) */
2309
2311
 
2310
2312
  /* hash all database names */
2311
 
  if (drizzle_query(&drizzle,"show databases") == 0)
 
2313
  if (drizzle_query_str(&con, &databases, "show databases", &ret) != NULL)
2312
2314
  {
2313
 
    if (!(databases = drizzle_store_result(&drizzle)))
2314
 
      put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
2315
 
    else
 
2315
    if (ret == DRIZZLE_RETURN_OK)
2316
2316
    {
2317
 
      while ((database_row=drizzle_fetch_row(databases)))
 
2317
      if (drizzle_result_buffer(&databases) != DRIZZLE_RETURN_OK)
 
2318
        put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
 
2319
      else
2318
2320
      {
2319
 
        char *str=strdup_root(&hash_mem_root, (char*) database_row[0]);
2320
 
        if (str)
2321
 
          add_word(&ht,(char*) str);
 
2321
        while ((database_row=drizzle_row_next(&databases)))
 
2322
        {
 
2323
          tmp_str= database_row[0];
 
2324
          tmp_str_lower= lower_string(tmp_str);
 
2325
          completion_map[tmp_str_lower]= tmp_str;
 
2326
        }
2322
2327
      }
2323
 
      drizzle_free_result(databases);
2324
2328
    }
 
2329
 
 
2330
    drizzle_result_free(&databases);
2325
2331
  }
 
2332
 
2326
2333
  /* hash all table names */
2327
 
  if (drizzle_query(&drizzle,"show tables")==0)
 
2334
  if (drizzle_query_str(&con, &tables, "show tables", &ret) != NULL)
2328
2335
  {
2329
 
    if (!(tables = drizzle_store_result(&drizzle)))
 
2336
    if (ret != DRIZZLE_RETURN_OK)
 
2337
    {
 
2338
      drizzle_result_free(&tables);
 
2339
      return;
 
2340
    }
 
2341
 
 
2342
    if (drizzle_result_buffer(&tables) != DRIZZLE_RETURN_OK)
2330
2343
      put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
2331
2344
    else
2332
2345
    {
2333
 
      if (drizzle_num_rows(tables) > 0 && !opt_silent && write_info)
 
2346
      if (drizzle_result_row_count(&tables) > 0 && !opt_silent && write_info)
2334
2347
      {
2335
2348
        tee_fprintf(stdout, _("\
2336
2349
Reading table information for completion of table and column names\n    \
2337
2350
You can turn off this feature to get a quicker startup with -A\n\n"));
2338
2351
      }
2339
 
      while ((table_row=drizzle_fetch_row(tables)))
 
2352
      while ((table_row=drizzle_row_next(&tables)))
2340
2353
      {
2341
 
        char *str=strdup_root(&hash_mem_root, (char*) table_row[0]);
2342
 
        if (str &&
2343
 
            !completion_hash_exists(&ht,(char*) str, (uint) strlen(str)))
2344
 
          add_word(&ht,str);
 
2354
        tmp_str= table_row[0];
 
2355
        tmp_str_lower= lower_string(tmp_str);
 
2356
        completion_map[tmp_str_lower]= tmp_str;
2345
2357
      }
2346
2358
    }
2347
2359
  }
 
2360
  else
 
2361
    return;
2348
2362
 
2349
2363
  /* hash all field names, both with the table prefix and without it */
2350
 
  if (!tables)          /* no tables */
2351
 
  {
2352
 
    return;
2353
 
  }
2354
 
  drizzle_data_seek(tables,0);
2355
 
  if (!(field_names= (char ***) alloc_root(&hash_mem_root,sizeof(char **) *
2356
 
                                           (uint) (drizzle_num_rows(tables)+1))))
2357
 
  {
2358
 
    drizzle_free_result(tables);
2359
 
    return;
2360
 
  }
2361
 
  i=0;
2362
 
  while ((table_row=drizzle_fetch_row(tables)))
2363
 
  {
2364
 
    if ((fields=drizzle_list_fields(&drizzle,(const char*) table_row[0],NULL)))
 
2364
  if (drizzle_result_row_count(&tables) == 0)
 
2365
  {
 
2366
    drizzle_result_free(&tables);
 
2367
    return;
 
2368
  }
 
2369
 
 
2370
  drizzle_row_seek(&tables, 0);
 
2371
 
 
2372
  while ((table_row=drizzle_row_next(&tables)))
 
2373
  {
 
2374
    string query;
 
2375
 
 
2376
    query.append("show fields in '");
 
2377
    query.append(table_row[0]);
 
2378
    query.append("'");
 
2379
    
 
2380
    if (drizzle_query(&con, &fields, query.c_str(), query.length(),
 
2381
                      &ret) != NULL)
2365
2382
    {
2366
 
      num_fields=drizzle_num_fields(fields);
2367
 
      if (!(field_names[i] = (char **) alloc_root(&hash_mem_root,
2368
 
                                                  sizeof(char *) *
2369
 
                                                  (num_fields*2+1))))
2370
 
      {
2371
 
        drizzle_free_result(fields);
2372
 
        break;
2373
 
      }
2374
 
      field_names[i][num_fields*2]= '\0';
2375
 
      j=0;
2376
 
      while ((sql_field=drizzle_fetch_field(fields)))
2377
 
      {
2378
 
        sprintf(buf,"%.64s.%.64s",table_row[0],sql_field->name);
2379
 
        field_names[i][j] = strdup_root(&hash_mem_root,buf);
2380
 
        add_word(&ht,field_names[i][j]);
2381
 
        field_names[i][num_fields+j] = strdup_root(&hash_mem_root,
2382
 
                                                   sql_field->name);
2383
 
        if (!completion_hash_exists(&ht,field_names[i][num_fields+j],
2384
 
                                    (uint) strlen(field_names[i][num_fields+j])))
2385
 
          add_word(&ht,field_names[i][num_fields+j]);
2386
 
        j++;
2387
 
      }
2388
 
      drizzle_free_result(fields);
 
2383
      if (ret == DRIZZLE_RETURN_OK &&
 
2384
          drizzle_result_buffer(&fields) == DRIZZLE_RETURN_OK)
 
2385
      {
 
2386
        while ((sql_field=drizzle_column_next(&fields)))
 
2387
        {
 
2388
          tmp_str=table_row[0];
 
2389
          tmp_str.append(".");
 
2390
          tmp_str.append(drizzle_column_name(sql_field));
 
2391
          tmp_str_lower= lower_string(tmp_str);
 
2392
          completion_map[tmp_str_lower]= tmp_str;
 
2393
 
 
2394
          tmp_str=drizzle_column_name(sql_field);
 
2395
          tmp_str_lower= lower_string(tmp_str);
 
2396
          completion_map[tmp_str_lower]= tmp_str;
 
2397
        }
 
2398
      }
 
2399
      drizzle_result_free(&fields);
2389
2400
    }
2390
 
    else
2391
 
      field_names[i]= 0;
2392
 
 
2393
 
    i++;
2394
2401
  }
2395
 
  drizzle_free_result(tables);
2396
 
  field_names[i]=0;        // End pointer
2397
 
  return;
 
2402
  drizzle_result_free(&tables);
 
2403
  completion_iter= completion_map.begin();
2398
2404
}
2399
2405
 
2400
2406
/* for gnu readline */
2442
2448
 
2443
2449
static void get_current_db(void)
2444
2450
{
2445
 
  DRIZZLE_RES *res;
 
2451
  drizzle_return_t ret;
 
2452
  drizzle_result_st res;
2446
2453
 
2447
2454
  free(current_db);
2448
2455
  current_db= NULL;
2449
2456
  /* In case of error below current_db will be NULL */
2450
 
  if (!drizzle_query(&drizzle, "SELECT DATABASE()") &&
2451
 
      (res= drizzle_use_result(&drizzle)))
 
2457
  if (drizzle_query_str(&con, &res, "SELECT DATABASE()", &ret) != NULL)
2452
2458
  {
2453
 
    DRIZZLE_ROW row= drizzle_fetch_row(res);
2454
 
    if (row[0])
2455
 
      current_db= strdup(row[0]);
2456
 
    drizzle_free_result(res);
 
2459
    if (ret == DRIZZLE_RETURN_OK &&
 
2460
        drizzle_result_buffer(&res) == DRIZZLE_RETURN_OK)
 
2461
    {
 
2462
      drizzle_row_t row= drizzle_row_next(&res);
 
2463
      if (row[0])
 
2464
        current_db= strdup(row[0]);
 
2465
    }
 
2466
    drizzle_result_free(&res);
2457
2467
  }
2458
2468
}
2459
2469
 
2461
2471
 The different commands
2462
2472
***************************************************************************/
2463
2473
 
2464
 
int drizzle_real_query_for_lazy(const char *buf, int length)
 
2474
int drizzleclient_real_query_for_lazy(const char *buf, int length,
 
2475
                                      drizzle_result_st *result,
 
2476
                                      uint32_t *error_code)
2465
2477
{
2466
 
  for (uint retry=0;; retry++)
 
2478
  drizzle_return_t ret;
 
2479
 
 
2480
  for (uint32_t retry=0;; retry++)
2467
2481
  {
2468
2482
    int error;
2469
 
    if (!drizzle_real_query(&drizzle,buf,length))
 
2483
    if (drizzle_query(&con,result,buf,length,&ret) != NULL &&
 
2484
        ret == DRIZZLE_RETURN_OK)
 
2485
    {
2470
2486
      return 0;
2471
 
    error= put_error(&drizzle);
2472
 
    if (drizzle_errno(&drizzle) != CR_SERVER_GONE_ERROR || retry > 1 ||
 
2487
    }
 
2488
    error= put_error(&con, result);
 
2489
 
 
2490
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2491
    {
 
2492
      *error_code= drizzle_result_error_code(result);
 
2493
      drizzle_result_free(result);
 
2494
    }
 
2495
 
 
2496
    if (ret != DRIZZLE_RETURN_SERVER_GONE || retry > 1 ||
2473
2497
        !opt_reconnect)
 
2498
    {
2474
2499
      return error;
 
2500
    }
 
2501
 
2475
2502
    if (reconnect())
2476
2503
      return error;
2477
2504
  }
2478
2505
}
2479
2506
 
2480
 
int drizzle_store_result_for_lazy(DRIZZLE_RES **result)
 
2507
int drizzleclient_store_result_for_lazy(drizzle_result_st *result)
2481
2508
{
2482
 
  if ((*result=drizzle_store_result(&drizzle)))
 
2509
  if (drizzle_result_buffer(result) == DRIZZLE_RETURN_OK)
2483
2510
    return 0;
2484
2511
 
2485
 
  if (drizzle_error(&drizzle)[0])
2486
 
    return put_error(&drizzle);
 
2512
  if (drizzle_con_error(&con)[0])
 
2513
    return put_error(&con, result);
2487
2514
  return 0;
2488
2515
}
2489
2516
 
2490
 
static void print_help_item(DRIZZLE_ROW *cur, int num_name, int num_cat, char *last_char)
2491
 
{
2492
 
  char ccat= (*cur)[num_cat][0];
2493
 
  if (*last_char != ccat)
2494
 
  {
2495
 
    put_info(ccat == 'Y' ? _("categories:") : _("topics:"), INFO_INFO,0,0);
2496
 
    *last_char= ccat;
2497
 
  }
2498
 
  tee_fprintf(PAGER, "   %s\n", (*cur)[num_name]);
2499
 
}
2500
 
 
2501
 
 
2502
 
static int com_server_help(string *buffer,
2503
 
                           const char *line __attribute__((unused)),
2504
 
                           char *help_arg)
2505
 
{
2506
 
  DRIZZLE_ROW cur;
2507
 
  const char *server_cmd= buffer->c_str();
2508
 
  char cmd_buf[100];
2509
 
  DRIZZLE_RES *result;
2510
 
  int error;
2511
 
 
2512
 
  if (help_arg[0] != '\'')
2513
 
  {
2514
 
    char *end_arg= strchr(help_arg, '\0');
2515
 
    if(--end_arg)
2516
 
    {
2517
 
      while (my_isspace(charset_info,*end_arg))
2518
 
        end_arg--;
2519
 
      *++end_arg= '\0';
2520
 
    }
2521
 
    (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NULL);
2522
 
    server_cmd= cmd_buf;
2523
 
  }
2524
 
 
2525
 
  if (!connected && reconnect())
2526
 
    return 1;
2527
 
 
2528
 
  if ((error= drizzle_real_query_for_lazy(server_cmd,(int)strlen(server_cmd))) ||
2529
 
      (error= drizzle_store_result_for_lazy(&result)))
2530
 
    return error;
2531
 
 
2532
 
  if (result)
2533
 
  {
2534
 
    unsigned int num_fields= drizzle_num_fields(result);
2535
 
    uint64_t num_rows= drizzle_num_rows(result);
2536
 
    drizzle_fetch_fields(result);
2537
 
    if (num_fields==3 && num_rows==1)
2538
 
    {
2539
 
      if (!(cur= drizzle_fetch_row(result)))
2540
 
      {
2541
 
        error= -1;
2542
 
        goto err;
2543
 
      }
2544
 
 
2545
 
      init_pager();
2546
 
      tee_fprintf(PAGER,   _("Name: \'%s\'\n"), cur[0]);
2547
 
      tee_fprintf(PAGER,   _("Description:\n%s"), cur[1]);
2548
 
      if (cur[2] && *((char*)cur[2]))
2549
 
        tee_fprintf(PAGER, _("Examples:\n%s"), cur[2]);
2550
 
      tee_fprintf(PAGER,   "\n");
2551
 
      end_pager();
2552
 
    }
2553
 
    else if (num_fields >= 2 && num_rows)
2554
 
    {
2555
 
      init_pager();
2556
 
      char last_char= 0;
2557
 
 
2558
 
      int num_name= 0, num_cat= 0;
2559
 
 
2560
 
      if (num_fields == 2)
2561
 
      {
2562
 
        put_info(_("Many help items for your request exist."), INFO_INFO,0,0);
2563
 
        put_info(_("To make a more specific request, please type 'help <item>',\nwhere <item> is one of the following"), INFO_INFO,0,0);
2564
 
        num_name= 0;
2565
 
        num_cat= 1;
2566
 
      }
2567
 
      else if ((cur= drizzle_fetch_row(result)))
2568
 
      {
2569
 
        tee_fprintf(PAGER, _("You asked for help about help category: '%s'\n"), cur[0]);
2570
 
        put_info(_("For more information, type 'help <item>', where <item> is one of the following"), INFO_INFO,0,0);
2571
 
        num_name= 1;
2572
 
        num_cat= 2;
2573
 
        print_help_item(&cur,1,2,&last_char);
2574
 
      }
2575
 
 
2576
 
      while ((cur= drizzle_fetch_row(result)))
2577
 
        print_help_item(&cur,num_name,num_cat,&last_char);
2578
 
      tee_fprintf(PAGER, "\n");
2579
 
      end_pager();
2580
 
    }
2581
 
    else
2582
 
    {
2583
 
      put_info(_("\nNothing found"), INFO_INFO,0,0);
2584
 
      put_info(_("Please try to run 'help contents' for a list of all accessible topics\n"), INFO_INFO,0,0);
2585
 
    }
2586
 
  }
2587
 
 
2588
 
err:
2589
 
  drizzle_free_result(result);
2590
 
  return error;
2591
 
}
2592
 
 
2593
2517
static int
2594
 
com_help(string *buffer __attribute__((unused)),
2595
 
         const char *line __attribute__((unused)))
 
2518
com_help(string *buffer, const char *)
2596
2519
{
2597
2520
  register int i, j;
2598
 
  char * help_arg= strchr(line,' '), buff[32], *end;
2599
 
  if (help_arg)
2600
 
  {
2601
 
    while (my_isspace(charset_info,*help_arg))
2602
 
      help_arg++;
2603
 
    if (*help_arg) return com_server_help(buffer,line,help_arg);
2604
 
  }
 
2521
  char buff[32], *end;
2605
2522
 
2606
2523
  put_info(_("List of all Drizzle commands:"), INFO_INFO,0,0);
2607
2524
  if (!named_cmds)
2608
2525
    put_info(_("Note that all text commands must be first on line and end with ';'"),INFO_INFO,0,0);
2609
2526
  for (i = 0; commands[i].name; i++)
2610
2527
  {
2611
 
    end= my_stpcpy(buff, commands[i].name);
 
2528
    end= strcpy(buff, commands[i].name);
 
2529
    end+= strlen(commands[i].name);
2612
2530
    for (j= (int)strlen(commands[i].name); j < 10; j++)
2613
 
      end= my_stpcpy(end, " ");
 
2531
      end= strcpy(end, " ")+1;
2614
2532
    if (commands[i].func)
2615
2533
      tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
2616
2534
                  commands[i].cmd_char, _(commands[i].doc));
2617
2535
  }
2618
 
  if (connected && drizzle_get_server_version(&drizzle) >= 40100)
2619
 
    put_info(_("\nFor server side help, type 'help contents'\n"), INFO_INFO,0,0);
 
2536
  tee_fprintf(stdout, "\n");
 
2537
  buffer->clear();
2620
2538
  return 0;
2621
2539
}
2622
2540
 
2623
2541
 
2624
2542
static int
2625
 
com_clear(string *buffer,
2626
 
          const char *line __attribute__((unused)))
 
2543
com_clear(string *buffer, const char *)
2627
2544
{
2628
2545
  if (status.add_to_history)
2629
2546
    fix_history(buffer);
2639
2556
  1  if fatal error
2640
2557
*/
2641
2558
static int
2642
 
com_go(string *buffer,
2643
 
       const char *line __attribute__((unused)))
 
2559
com_go(string *buffer, const char *)
2644
2560
{
2645
2561
  char          buff[200]; /* about 110 chars used so far */
2646
2562
  char          time_buff[52+3+1]; /* time max + space&parens + NUL */
2647
 
  DRIZZLE_RES     *result;
2648
 
  uint32_t         timer, warnings= 0;
2649
 
  uint          error= 0;
 
2563
  drizzle_result_st result;
 
2564
  drizzle_return_t ret;
 
2565
  uint32_t      timer, warnings= 0;
 
2566
  uint32_t      error= 0;
 
2567
  uint32_t      error_code= 0;
2650
2568
  int           err= 0;
2651
2569
 
2652
2570
  interrupted_query= 0;
2680
2598
 
2681
2599
  timer=start_timer();
2682
2600
  executing_query= 1;
2683
 
  error= drizzle_real_query_for_lazy(buffer->c_str(),buffer->length());
 
2601
  error= drizzleclient_real_query_for_lazy(buffer->c_str(),buffer->length(),&result, &error_code);
2684
2602
 
2685
2603
  if (status.add_to_history)
2686
2604
  {
2700
2618
 
2701
2619
    if (quick)
2702
2620
    {
2703
 
      if (!(result=drizzle_use_result(&drizzle)) && drizzle_field_count(&drizzle))
 
2621
      if (drizzle_column_buffer(&result) != DRIZZLE_RETURN_OK)
2704
2622
      {
2705
 
        error= put_error(&drizzle);
 
2623
        error= put_error(&con, &result);
2706
2624
        goto end;
2707
2625
      }
2708
2626
    }
2709
2627
    else
2710
2628
    {
2711
 
      error= drizzle_store_result_for_lazy(&result);
 
2629
      error= drizzleclient_store_result_for_lazy(&result);
2712
2630
      if (error)
2713
2631
        goto end;
2714
2632
    }
2719
2637
      time_buff[0]= '\0';
2720
2638
 
2721
2639
    /* Every branch must truncate  buff . */
2722
 
    if (result)
 
2640
    if (drizzle_result_column_count(&result) > 0)
2723
2641
    {
2724
 
      if (!drizzle_num_rows(result) && ! quick && !column_types_flag)
 
2642
      if (!quick && drizzle_result_row_count(&result) == 0 &&
 
2643
          !column_types_flag)
2725
2644
      {
2726
 
        my_stpcpy(buff, _("Empty set"));
 
2645
        strcpy(buff, _("Empty set"));
2727
2646
      }
2728
2647
      else
2729
2648
      {
2730
2649
        init_pager();
2731
2650
        if (vertical || (auto_vertical_output &&
2732
 
                         (terminal_width < get_result_width(result))))
2733
 
          print_table_data_vertically(result);
 
2651
                         (terminal_width < get_result_width(&result))))
 
2652
          print_table_data_vertically(&result);
2734
2653
        else if (opt_silent && verbose <= 2 && !output_tables)
2735
 
          print_tab_data(result);
 
2654
          print_tab_data(&result);
2736
2655
        else
2737
 
          print_table_data(result);
 
2656
          print_table_data(&result);
2738
2657
        sprintf(buff,
2739
2658
                ngettext("%ld row in set","%ld rows in set",
2740
 
                         (long) drizzle_num_rows(result)),
2741
 
                (long) drizzle_num_rows(result));
 
2659
                         (long) drizzle_result_row_count(&result)),
 
2660
                (long) drizzle_result_row_count(&result));
2742
2661
        end_pager();
2743
 
        if (drizzle_errno(&drizzle))
2744
 
          error= put_error(&drizzle);
 
2662
        if (drizzle_result_error_code(&result))
 
2663
          error= put_error(&con, &result);
2745
2664
      }
2746
2665
    }
2747
 
    else if (drizzle_affected_rows(&drizzle) == ~(uint64_t) 0)
2748
 
      my_stpcpy(buff,_("Query OK"));
 
2666
    else if (drizzle_result_affected_rows(&result) == ~(uint64_t) 0)
 
2667
      strcpy(buff,_("Query OK"));
2749
2668
    else
2750
2669
      sprintf(buff, ngettext("Query OK, %ld row affected",
2751
2670
                             "Query OK, %ld rows affected",
2752
 
                             (long) drizzle_affected_rows(&drizzle)),
2753
 
              (long) drizzle_affected_rows(&drizzle));
 
2671
                             (long) drizzle_result_affected_rows(&result)),
 
2672
              (long) drizzle_result_affected_rows(&result));
2754
2673
 
2755
2674
    pos= strchr(buff, '\0');
2756
 
    if ((warnings= drizzle_warning_count(&drizzle)))
 
2675
    if ((warnings= drizzle_result_warning_count(&result)))
2757
2676
    {
2758
2677
      *pos++= ',';
2759
2678
      *pos++= ' ';
2760
 
      pos=int10_to_str(warnings, pos, 10);
2761
 
      pos=my_stpcpy(pos, " warning");
 
2679
      pos= int10_to_str(warnings, pos, 10);
 
2680
      pos= strcpy(pos, " warning")+8;
2762
2681
      if (warnings != 1)
2763
2682
        *pos++= 's';
2764
2683
    }
2765
 
    my_stpcpy(pos, time_buff);
 
2684
    strcpy(pos, time_buff);
2766
2685
    put_info(buff,INFO_RESULT,0,0);
2767
 
    if (drizzle_info(&drizzle))
2768
 
      put_info(drizzle_info(&drizzle),INFO_RESULT,0,0);
 
2686
    if (strcmp(drizzle_result_info(&result), ""))
 
2687
      put_info(drizzle_result_info(&result),INFO_RESULT,0,0);
2769
2688
    put_info("",INFO_RESULT,0,0);      // Empty row
2770
2689
 
2771
 
    if (result && !drizzle_eof(result))  /* Something wrong when using quick */
2772
 
      error= put_error(&drizzle);
2773
 
    else if (unbuffered)
 
2690
    if (unbuffered)
2774
2691
      fflush(stdout);
2775
 
    drizzle_free_result(result);
2776
 
  } while (!(err= drizzle_next_result(&drizzle)));
 
2692
    drizzle_result_free(&result);
 
2693
 
 
2694
    if (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS)
 
2695
    {
 
2696
      if (drizzle_result_read(&con, &result, &ret) == NULL ||
 
2697
          ret != DRIZZLE_RETURN_OK)
 
2698
      {
 
2699
        if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2700
        {
 
2701
          error_code= drizzle_result_error_code(&result);
 
2702
          drizzle_result_free(&result);
 
2703
        }
 
2704
 
 
2705
        error= put_error(&con, NULL);
 
2706
        goto end;
 
2707
      }
 
2708
    }
 
2709
 
 
2710
  } while (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS);
2777
2711
  if (err >= 1)
2778
 
    error= put_error(&drizzle);
 
2712
    error= put_error(&con, NULL);
2779
2713
 
2780
2714
end:
2781
2715
 
2782
2716
  /* Show warnings if any or error occured */
2783
2717
  if (show_warnings == 1 && (warnings >= 1 || error))
2784
 
    print_warnings();
 
2718
    print_warnings(error_code);
2785
2719
 
2786
2720
  if (!error && !status.batch &&
2787
 
      (drizzle.server_status & SERVER_STATUS_DB_DROPPED))
 
2721
      drizzle_con_status(&con) & DRIZZLE_CON_STATUS_DB_DROPPED)
 
2722
  {
2788
2723
    get_current_db();
 
2724
  }
2789
2725
 
2790
2726
  executing_query= 0;
2791
2727
  return error;        /* New command follows */
2818
2754
  FILE* new_outfile;
2819
2755
  if (opt_outfile)
2820
2756
    end_tee();
2821
 
  if (!(new_outfile= my_fopen(file_name, O_APPEND | O_WRONLY, MYF(MY_WME))))
 
2757
  if (!(new_outfile= fopen(file_name, "a")))
2822
2758
  {
2823
2759
    tee_fprintf(stdout, "Error logging to file '%s'\n", file_name);
2824
2760
    return;
2825
2761
  }
2826
2762
  OUTFILE = new_outfile;
2827
 
  strmake(outfile, file_name, FN_REFLEN-1);
 
2763
  strncpy(outfile, file_name, FN_REFLEN-1);
2828
2764
  tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
2829
2765
  opt_outfile= 1;
 
2766
 
2830
2767
  return;
2831
2768
}
2832
2769
 
2833
2770
 
2834
2771
static void end_tee()
2835
2772
{
2836
 
  my_fclose(OUTFILE, MYF(0));
 
2773
  fclose(OUTFILE);
2837
2774
  OUTFILE= 0;
2838
2775
  opt_outfile= 0;
2839
2776
  return;
2852
2789
}
2853
2790
 
2854
2791
 
2855
 
static const char *fieldtype2str(enum enum_field_types type)
 
2792
static const char *fieldtype2str(drizzle_column_type_t type)
2856
2793
{
2857
2794
  switch (type) {
2858
 
    case DRIZZLE_TYPE_BLOB:        return "BLOB";
2859
 
    case DRIZZLE_TYPE_NEWDATE:        return "DATE";
2860
 
    case DRIZZLE_TYPE_DATETIME:    return "DATETIME";
2861
 
    case DRIZZLE_TYPE_NEWDECIMAL:  return "DECIMAL";
2862
 
    case DRIZZLE_TYPE_DOUBLE:      return "DOUBLE";
2863
 
    case DRIZZLE_TYPE_ENUM:        return "ENUM";
2864
 
    case DRIZZLE_TYPE_LONG:        return "LONG";
2865
 
    case DRIZZLE_TYPE_LONGLONG:    return "LONGLONG";
2866
 
    case DRIZZLE_TYPE_NULL:        return "NULL";
2867
 
    case DRIZZLE_TYPE_TIME:        return "TIME";
2868
 
    case DRIZZLE_TYPE_TIMESTAMP:   return "TIMESTAMP";
2869
 
    case DRIZZLE_TYPE_TINY:        return "TINY";
 
2795
    case DRIZZLE_COLUMN_TYPE_BLOB:        return "BLOB";
 
2796
    case DRIZZLE_COLUMN_TYPE_DATE:        return "DATE";
 
2797
    case DRIZZLE_COLUMN_TYPE_DATETIME:    return "DATETIME";
 
2798
    case DRIZZLE_COLUMN_TYPE_NEWDECIMAL:  return "DECIMAL";
 
2799
    case DRIZZLE_COLUMN_TYPE_DOUBLE:      return "DOUBLE";
 
2800
    case DRIZZLE_COLUMN_TYPE_ENUM:        return "ENUM";
 
2801
    case DRIZZLE_COLUMN_TYPE_LONG:        return "LONG";
 
2802
    case DRIZZLE_COLUMN_TYPE_LONGLONG:    return "LONGLONG";
 
2803
    case DRIZZLE_COLUMN_TYPE_NULL:        return "NULL";
 
2804
    case DRIZZLE_COLUMN_TYPE_TIMESTAMP:   return "TIMESTAMP";
 
2805
    case DRIZZLE_COLUMN_TYPE_TINY:        return "TINY";
 
2806
    case DRIZZLE_COLUMN_TYPE_VIRTUAL:     return "VIRTUAL";
2870
2807
    default:                     return "?-unknown-?";
2871
2808
  }
2872
2809
}
2873
2810
 
2874
 
static char *fieldflags2str(uint f) {
 
2811
static char *fieldflags2str(uint32_t f) {
2875
2812
  static char buf[1024];
2876
2813
  char *s=buf;
2877
2814
  *s=0;
2878
2815
#define ff2s_check_flag(X)                                              \
2879
 
  if (f & X ## _FLAG) { s=my_stpcpy(s, # X " "); f &= ~ X ## _FLAG; }
 
2816
  if (f & DRIZZLE_COLUMN_FLAGS_ ## X) { s=strcpy(s, # X " ")+strlen(# X " "); \
 
2817
                        f &= ~ DRIZZLE_COLUMN_FLAGS_ ## X; }
2880
2818
  ff2s_check_flag(NOT_NULL);
2881
2819
  ff2s_check_flag(PRI_KEY);
2882
2820
  ff2s_check_flag(UNIQUE_KEY);
2902
2840
}
2903
2841
 
2904
2842
static void
2905
 
print_field_types(DRIZZLE_RES *result)
 
2843
print_field_types(drizzle_result_st *result)
2906
2844
{
2907
 
  DRIZZLE_FIELD   *field;
2908
 
  uint i=0;
 
2845
  drizzle_column_st   *field;
 
2846
  uint32_t i=0;
2909
2847
 
2910
 
  while ((field = drizzle_fetch_field(result)))
 
2848
  while ((field = drizzle_column_next(result)))
2911
2849
  {
2912
2850
    tee_fprintf(PAGER, "Field %3u:  `%s`\n"
2913
2851
                "Catalog:    `%s`\n"
2921
2859
                "Decimals:   %u\n"
2922
2860
                "Flags:      %s\n\n",
2923
2861
                ++i,
2924
 
                field->name, field->catalog, field->db, field->table,
2925
 
                field->org_table, fieldtype2str(field->type),
2926
 
                get_charset_name(field->charsetnr), field->charsetnr,
2927
 
                field->length, field->max_length, field->decimals,
2928
 
                fieldflags2str(field->flags));
 
2862
                drizzle_column_name(field), drizzle_column_catalog(field),
 
2863
                drizzle_column_db(field), drizzle_column_table(field),
 
2864
                drizzle_column_orig_table(field),
 
2865
                fieldtype2str(drizzle_column_type(field)),
 
2866
                get_charset_name(drizzle_column_charset(field)),
 
2867
                drizzle_column_charset(field), drizzle_column_size(field),
 
2868
                drizzle_column_max_size(field), drizzle_column_decimals(field),
 
2869
                fieldflags2str(drizzle_column_flags(field)));
2929
2870
  }
2930
2871
  tee_puts("", PAGER);
2931
2872
}
2932
2873
 
2933
2874
 
2934
2875
static void
2935
 
print_table_data(DRIZZLE_RES *result)
 
2876
print_table_data(drizzle_result_st *result)
2936
2877
{
2937
 
  DRIZZLE_ROW     cur;
2938
 
  DRIZZLE_FIELD   *field;
2939
 
  bool          *num_flag;
 
2878
  drizzle_row_t cur;
 
2879
  drizzle_return_t ret;
 
2880
  drizzle_column_st *field;
 
2881
  bool *num_flag;
2940
2882
  string separator;
2941
 
  
 
2883
 
2942
2884
  separator.reserve(256);
2943
2885
 
2944
 
  num_flag=(bool*) my_malloc(sizeof(bool)*drizzle_num_fields(result),
2945
 
                             MYF(MY_WME));
 
2886
  num_flag=(bool*) malloc(sizeof(bool)*drizzle_result_column_count(result));
2946
2887
  if (column_types_flag)
2947
2888
  {
2948
2889
    print_field_types(result);
2949
 
    if (!drizzle_num_rows(result))
 
2890
    if (!drizzle_result_row_count(result))
2950
2891
      return;
2951
 
    drizzle_field_seek(result,0);
 
2892
    drizzle_column_seek(result,0);
2952
2893
  }
2953
2894
  separator.append("+");
2954
 
  while ((field = drizzle_fetch_field(result)))
 
2895
  while ((field = drizzle_column_next(result)))
2955
2896
  {
2956
 
    uint32_t length= column_names ? field->name_length : 0;
 
2897
    uint32_t x, length= 0;
 
2898
 
 
2899
    if (column_names)
 
2900
    {
 
2901
      uint32_t name_length= strlen(drizzle_column_name(field));
 
2902
 
 
2903
      /* Check if the max_byte value is really the maximum in terms
 
2904
         of visual length since multibyte characters can affect the
 
2905
         length of the separator. */
 
2906
      length= charset_info->cset->numcells(charset_info,
 
2907
                                           drizzle_column_name(field),
 
2908
                                           drizzle_column_name(field) +
 
2909
                                           name_length);
 
2910
 
 
2911
      if (name_length == drizzle_column_max_size(field))
 
2912
      {
 
2913
        if (length < drizzle_column_max_size(field))
 
2914
          drizzle_column_set_max_size(field, length);
 
2915
      }
 
2916
      else
 
2917
      {
 
2918
        length= name_length;
 
2919
      }
 
2920
    }
 
2921
  
2957
2922
    if (quick)
2958
 
      length=max(length,field->length);
 
2923
      length=max(length,drizzle_column_size(field));
2959
2924
    else
2960
 
      length=max(length,field->max_length);
2961
 
    if (length < 4 && !(field->flags & NOT_NULL_FLAG))
 
2925
      length=max(length,(uint32_t)drizzle_column_max_size(field));
 
2926
    if (length < 4 &&
 
2927
        !(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
 
2928
    {
2962
2929
      // Room for "NULL"
2963
2930
      length=4;
2964
 
    field->max_length=length;
2965
 
    uint x;
 
2931
    }
 
2932
    drizzle_column_set_max_size(field, length);
 
2933
 
2966
2934
    for (x=0; x< (length+2); x++)
2967
2935
      separator.append("-");
2968
2936
    separator.append("+");
2971
2939
  tee_puts((char*) separator.c_str(), PAGER);
2972
2940
  if (column_names)
2973
2941
  {
2974
 
    drizzle_field_seek(result,0);
 
2942
    drizzle_column_seek(result,0);
2975
2943
    (void) tee_fputs("|", PAGER);
2976
 
    for (uint off=0; (field = drizzle_fetch_field(result)) ; off++)
 
2944
    for (uint32_t off=0; (field = drizzle_column_next(result)) ; off++)
2977
2945
    {
2978
 
      uint name_length= (uint) strlen(field->name);
2979
 
      uint numcells= charset_info->cset->numcells(charset_info,
2980
 
                                                  field->name,
2981
 
                                                  field->name + name_length);
2982
 
      uint32_t display_length= field->max_length + name_length - numcells;
 
2946
      uint32_t name_length= (uint32_t) strlen(drizzle_column_name(field));
 
2947
      uint32_t numcells= charset_info->cset->numcells(charset_info,
 
2948
                                                  drizzle_column_name(field),
 
2949
                                                  drizzle_column_name(field) +
 
2950
                                                  name_length);
 
2951
      uint32_t display_length= drizzle_column_max_size(field) + name_length -
 
2952
                               numcells;
2983
2953
      tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
2984
2954
                                             MAX_COLUMN_LENGTH),
2985
 
                  field->name);
2986
 
      num_flag[off]= ((field->type <= DRIZZLE_TYPE_LONGLONG) || 
2987
 
                      (field->type == DRIZZLE_TYPE_NEWDECIMAL));
 
2955
                  drizzle_column_name(field));
 
2956
      num_flag[off]= ((drizzle_column_type(field) <= DRIZZLE_COLUMN_TYPE_LONGLONG) ||
 
2957
                      (drizzle_column_type(field) == DRIZZLE_COLUMN_TYPE_NEWDECIMAL));
2988
2958
    }
2989
2959
    (void) tee_fputs("\n", PAGER);
2990
2960
    tee_puts((char*) separator.c_str(), PAGER);
2991
2961
  }
2992
2962
 
2993
 
  while ((cur= drizzle_fetch_row(result)))
 
2963
  while (1)
2994
2964
  {
2995
 
    if (interrupted_query)
 
2965
    if (quick)
 
2966
    {
 
2967
      cur= drizzle_row_buffer(result, &ret);
 
2968
      if (ret != DRIZZLE_RETURN_OK)
 
2969
      {
 
2970
        (void)put_error(&con, result);
 
2971
        break;
 
2972
      }
 
2973
    }
 
2974
    else
 
2975
      cur= drizzle_row_next(result);
 
2976
 
 
2977
    if (cur == NULL || interrupted_query)
2996
2978
      break;
2997
 
    uint32_t *lengths= drizzle_fetch_lengths(result);
 
2979
 
 
2980
    size_t *lengths= drizzle_row_field_sizes(result);
2998
2981
    (void) tee_fputs("| ", PAGER);
2999
 
    drizzle_field_seek(result, 0);
3000
 
    for (uint off= 0; off < drizzle_num_fields(result); off++)
 
2982
    drizzle_column_seek(result, 0);
 
2983
    for (uint32_t off= 0; off < drizzle_result_column_count(result); off++)
3001
2984
    {
3002
2985
      const char *buffer;
3003
 
      uint data_length;
3004
 
      uint field_max_length;
3005
 
      uint visible_length;
3006
 
      uint extra_padding;
 
2986
      uint32_t data_length;
 
2987
      uint32_t field_max_length;
 
2988
      uint32_t visible_length;
 
2989
      uint32_t extra_padding;
3007
2990
 
3008
2991
      if (cur[off] == NULL)
3009
2992
      {
3013
2996
      else
3014
2997
      {
3015
2998
        buffer= cur[off];
3016
 
        data_length= (uint) lengths[off];
 
2999
        data_length= (uint32_t) lengths[off];
3017
3000
      }
3018
3001
 
3019
 
      field= drizzle_fetch_field(result);
3020
 
      field_max_length= field->max_length;
 
3002
      field= drizzle_column_next(result);
 
3003
      field_max_length= drizzle_column_max_size(field);
3021
3004
 
3022
3005
      /*
3023
3006
        How many text cells on the screen will this string span?  If it contains
3043
3026
      tee_fputs(" | ", PAGER);
3044
3027
    }
3045
3028
    (void) tee_fputs("\n", PAGER);
 
3029
    if (quick)
 
3030
      drizzle_row_free(result, cur);
3046
3031
  }
3047
3032
  tee_puts(separator.c_str(), PAGER);
3048
3033
  free(num_flag);
3064
3049
 
3065
3050
   @returns  number of character positions to be used, at most
3066
3051
*/
3067
 
static int get_field_disp_length(DRIZZLE_FIELD *field)
 
3052
static int get_field_disp_length(drizzle_column_st *field)
3068
3053
{
3069
 
  uint length= column_names ? field->name_length : 0;
 
3054
  uint32_t length= column_names ? strlen(drizzle_column_name(field)) : 0;
3070
3055
 
3071
3056
  if (quick)
3072
 
    length= max(length, field->length);
 
3057
    length= max(length, drizzle_column_size(field));
3073
3058
  else
3074
 
    length= max(length, field->max_length);
 
3059
    length= max(length, (uint32_t)drizzle_column_max_size(field));
3075
3060
 
3076
 
  if (length < 4 && !(field->flags & NOT_NULL_FLAG))
 
3061
  if (length < 4 &&
 
3062
    !(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
 
3063
  {
3077
3064
    length= 4;        /* Room for "NULL" */
 
3065
  }
3078
3066
 
3079
3067
  return length;
3080
3068
}
3087
3075
 
3088
3076
   @returns  The max number of characters in any row of this result
3089
3077
*/
3090
 
static int get_result_width(DRIZZLE_RES *result)
 
3078
static int get_result_width(drizzle_result_st *result)
3091
3079
{
3092
3080
  unsigned int len= 0;
3093
 
  DRIZZLE_FIELD *field;
3094
 
  DRIZZLE_FIELD_OFFSET offset;
 
3081
  drizzle_column_st *field;
 
3082
  uint16_t offset;
3095
3083
 
3096
 
  offset= drizzle_field_tell(result);
 
3084
  offset= drizzle_column_current(result);
3097
3085
  assert(offset == 0);
3098
3086
 
3099
 
  while ((field= drizzle_fetch_field(result)) != NULL)
 
3087
  while ((field= drizzle_column_next(result)) != NULL)
3100
3088
    len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
3101
3089
 
3102
 
  (void) drizzle_field_seek(result, offset);
 
3090
  (void) drizzle_column_seek(result, offset);
3103
3091
 
3104
3092
  return len + 1; /* plus final bar. */
3105
3093
}
3135
3123
 
3136
3124
 
3137
3125
static void
3138
 
print_table_data_vertically(DRIZZLE_RES *result)
 
3126
print_table_data_vertically(drizzle_result_st *result)
3139
3127
{
3140
 
  DRIZZLE_ROW  cur;
3141
 
  uint    max_length=0;
3142
 
  DRIZZLE_FIELD  *field;
 
3128
  drizzle_row_t cur;
 
3129
  drizzle_return_t ret;
 
3130
  uint32_t max_length=0;
 
3131
  drizzle_column_st *field;
3143
3132
 
3144
 
  while ((field = drizzle_fetch_field(result)))
 
3133
  while ((field = drizzle_column_next(result)))
3145
3134
  {
3146
 
    uint length= field->name_length;
 
3135
    uint32_t length= strlen(drizzle_column_name(field));
3147
3136
    if (length > max_length)
3148
3137
      max_length= length;
3149
 
    field->max_length=length;
 
3138
    drizzle_column_set_max_size(field, length);
3150
3139
  }
3151
3140
 
3152
 
  drizzle_field_seek(result,0);
3153
 
  for (uint row_count=1; (cur= drizzle_fetch_row(result)); row_count++)
 
3141
  for (uint32_t row_count=1;; row_count++)
3154
3142
  {
3155
 
    if (interrupted_query)
 
3143
    if (quick)
 
3144
    {
 
3145
      cur= drizzle_row_buffer(result, &ret);
 
3146
      if (ret != DRIZZLE_RETURN_OK)
 
3147
      {
 
3148
        (void)put_error(&con, result);
 
3149
        break;
 
3150
      }
 
3151
    }
 
3152
    else
 
3153
      cur= drizzle_row_next(result);
 
3154
 
 
3155
    if (cur == NULL || interrupted_query)
3156
3156
      break;
3157
 
    drizzle_field_seek(result,0);
 
3157
    drizzle_column_seek(result,0);
3158
3158
    tee_fprintf(PAGER,
3159
3159
                "*************************** %d. row ***************************\n", row_count);
3160
 
    for (uint off=0; off < drizzle_num_fields(result); off++)
 
3160
    for (uint32_t off=0; off < drizzle_result_column_count(result); off++)
3161
3161
    {
3162
 
      field= drizzle_fetch_field(result);
3163
 
      tee_fprintf(PAGER, "%*s: ",(int) max_length,field->name);
 
3162
      field= drizzle_column_next(result);
 
3163
      tee_fprintf(PAGER, "%*s: ",(int) max_length,drizzle_column_name(field));
3164
3164
      tee_fprintf(PAGER, "%s\n",cur[off] ? (char*) cur[off] : "NULL");
3165
3165
    }
 
3166
    if (quick)
 
3167
      drizzle_row_free(result, cur);
3166
3168
  }
3167
3169
}
3168
3170
 
3169
3171
 
3170
3172
/* print_warnings should be called right after executing a statement */
3171
3173
 
3172
 
static void print_warnings()
 
3174
static void print_warnings(uint32_t error_code)
3173
3175
{
3174
 
  const char   *query;
3175
 
  DRIZZLE_RES    *result;
3176
 
  DRIZZLE_ROW    cur;
 
3176
  const char *query;
 
3177
  drizzle_result_st result;
 
3178
  drizzle_row_t cur;
3177
3179
  uint64_t num_rows;
3178
 
 
3179
 
  /* Save current error before calling "show warnings" */
3180
 
  uint error= drizzle_errno(&drizzle);
 
3180
  uint32_t new_code= 0;
3181
3181
 
3182
3182
  /* Get the warnings */
3183
3183
  query= "show warnings";
3184
 
  drizzle_real_query_for_lazy(query, strlen(query));
3185
 
  drizzle_store_result_for_lazy(&result);
 
3184
  drizzleclient_real_query_for_lazy(query, strlen(query),&result,&new_code);
 
3185
  drizzleclient_store_result_for_lazy(&result);
3186
3186
 
3187
3187
  /* Bail out when no warnings */
3188
 
  if (!(num_rows= drizzle_num_rows(result)))
 
3188
  if (!(num_rows= drizzle_result_row_count(&result)))
3189
3189
    goto end;
3190
3190
 
3191
 
  cur= drizzle_fetch_row(result);
 
3191
  cur= drizzle_row_next(&result);
3192
3192
 
3193
3193
  /*
3194
3194
    Don't print a duplicate of the current error.  It is possible for SHOW
3196
3196
    messages.  To be safe, skip printing the duplicate only if it is the only
3197
3197
    warning.
3198
3198
  */
3199
 
  if (!cur || (num_rows == 1 && error == (uint) strtoul(cur[1], NULL, 10)))
 
3199
  if (!cur || (num_rows == 1 &&
 
3200
      error_code == (uint32_t) strtoul(cur[1], NULL, 10)))
 
3201
  {
3200
3202
    goto end;
 
3203
  }
3201
3204
 
3202
3205
  /* Print the warnings */
3203
3206
  init_pager();
3204
3207
  do
3205
3208
  {
3206
3209
    tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]);
3207
 
  } while ((cur= drizzle_fetch_row(result)));
 
3210
  } while ((cur= drizzle_row_next(&result)));
3208
3211
  end_pager();
3209
3212
 
3210
3213
end:
3211
 
  drizzle_free_result(result);
 
3214
  drizzle_result_free(&result);
3212
3215
}
3213
3216
 
3214
3217
 
3250
3253
 
3251
3254
 
3252
3255
static void
3253
 
print_tab_data(DRIZZLE_RES *result)
 
3256
print_tab_data(drizzle_result_st *result)
3254
3257
{
3255
 
  DRIZZLE_ROW  cur;
3256
 
  DRIZZLE_FIELD  *field;
3257
 
  uint32_t    *lengths;
 
3258
  drizzle_row_t cur;
 
3259
  drizzle_return_t ret;
 
3260
  drizzle_column_st *field;
 
3261
  size_t *lengths;
3258
3262
 
3259
3263
  if (opt_silent < 2 && column_names)
3260
3264
  {
3261
3265
    int first=0;
3262
 
    while ((field = drizzle_fetch_field(result)))
 
3266
    while ((field = drizzle_column_next(result)))
3263
3267
    {
3264
3268
      if (first++)
3265
3269
        (void) tee_fputs("\t", PAGER);
3266
 
      (void) tee_fputs(field->name, PAGER);
 
3270
      (void) tee_fputs(drizzle_column_name(field), PAGER);
3267
3271
    }
3268
3272
    (void) tee_fputs("\n", PAGER);
3269
3273
  }
3270
 
  while ((cur = drizzle_fetch_row(result)))
 
3274
  while (1)
3271
3275
  {
3272
 
    lengths= drizzle_fetch_lengths(result);
 
3276
    if (quick)
 
3277
    {
 
3278
      cur= drizzle_row_buffer(result, &ret);
 
3279
      if (ret != DRIZZLE_RETURN_OK)
 
3280
      {
 
3281
        (void)put_error(&con, result);
 
3282
        break;
 
3283
      }
 
3284
    }
 
3285
    else
 
3286
      cur= drizzle_row_next(result);
 
3287
 
 
3288
    if (cur == NULL)
 
3289
      break;
 
3290
 
 
3291
    lengths= drizzle_row_field_sizes(result);
3273
3292
    safe_put_field(cur[0],lengths[0]);
3274
 
    for (uint off=1 ; off < drizzle_num_fields(result); off++)
 
3293
    for (uint32_t off=1 ; off < drizzle_result_column_count(result); off++)
3275
3294
    {
3276
3295
      (void) tee_fputs("\t", PAGER);
3277
3296
      safe_put_field(cur[off], lengths[off]);
3278
3297
    }
3279
3298
    (void) tee_fputs("\n", PAGER);
 
3299
    if (quick)
 
3300
      drizzle_row_free(result, cur);
3280
3301
  }
3281
3302
}
3282
3303
 
3283
3304
static int
3284
 
com_tee(string *buffer __attribute__((unused)), const char *line )
 
3305
com_tee(string *, const char *line )
3285
3306
{
3286
 
  char file_name[FN_REFLEN], *end, *param;
 
3307
  char file_name[FN_REFLEN], *end;
 
3308
  const char *param;
3287
3309
 
3288
3310
  if (status.batch)
3289
3311
    return 0;
3308
3330
  /* eliminate the spaces before the parameters */
3309
3331
  while (my_isspace(charset_info,*param))
3310
3332
    param++;
3311
 
  end= strmake(file_name, param, sizeof(file_name) - 1);
 
3333
  strncpy(file_name, param, sizeof(file_name) - 1);
 
3334
  end= file_name + strlen(file_name);
3312
3335
  /* remove end space from command line */
3313
3336
  while (end > file_name && (my_isspace(charset_info,end[-1]) ||
3314
3337
                             my_iscntrl(charset_info,end[-1])))
3325
3348
 
3326
3349
 
3327
3350
static int
3328
 
com_notee(string *buffer __attribute__((unused)),
3329
 
          const char *line __attribute__((unused)))
 
3351
com_notee(string *, const char *)
3330
3352
{
3331
3353
  if (opt_outfile)
3332
3354
    end_tee();
3339
3361
*/
3340
3362
 
3341
3363
static int
3342
 
com_pager(string *buffer __attribute__((unused)),
3343
 
          const char *line __attribute__((unused)))
 
3364
com_pager(string *, const char *line)
3344
3365
{
3345
 
  char pager_name[FN_REFLEN], *end, *param;
 
3366
  char pager_name[FN_REFLEN], *end;
 
3367
  const char *param;
3346
3368
 
3347
3369
  if (status.batch)
3348
3370
    return 0;
3360
3382
    {
3361
3383
      tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
3362
3384
      opt_nopager=1;
3363
 
      my_stpcpy(pager, "stdout");
 
3385
      strcpy(pager, "stdout");
3364
3386
      PAGER= stdout;
3365
3387
      return 0;
3366
3388
    }
3367
 
    my_stpcpy(pager, default_pager);
 
3389
    strcpy(pager, default_pager);
3368
3390
  }
3369
3391
  else
3370
3392
  {
3371
 
    end= strmake(pager_name, param, sizeof(pager_name)-1);
 
3393
    end= strncpy(pager_name, param, sizeof(pager_name)-1);
 
3394
    end+= strlen(pager_name);
3372
3395
    while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
3373
3396
                                my_iscntrl(charset_info,end[-1])))
3374
3397
      end--;
3375
3398
    end[0]=0;
3376
 
    my_stpcpy(pager, pager_name);
3377
 
    my_stpcpy(default_pager, pager_name);
 
3399
    strcpy(pager, pager_name);
 
3400
    strcpy(default_pager, pager_name);
3378
3401
  }
3379
3402
  opt_nopager=0;
3380
3403
  tee_fprintf(stdout, "PAGER set to '%s'\n", pager);
3383
3406
 
3384
3407
 
3385
3408
static int
3386
 
com_nopager(string *buffer __attribute__((unused)),
3387
 
            const char *line __attribute__((unused)))
 
3409
com_nopager(string *, const char *)
3388
3410
{
3389
 
  my_stpcpy(pager, "stdout");
 
3411
  strcpy(pager, "stdout");
3390
3412
  opt_nopager=1;
3391
3413
  PAGER= stdout;
3392
3414
  tee_fprintf(stdout, "PAGER set to stdout\n");
3396
3418
/* If arg is given, exit without errors. This happens on command 'quit' */
3397
3419
 
3398
3420
static int
3399
 
com_quit(string *buffer __attribute__((unused)),
3400
 
         const char *line __attribute__((unused)))
 
3421
com_quit(string *, const char *)
3401
3422
{
3402
3423
  /* let the screen auto close on a normal shutdown */
3403
3424
  status.exit_status=0;
3405
3426
}
3406
3427
 
3407
3428
static int
3408
 
com_rehash(string *buffer __attribute__((unused)),
3409
 
           const char *line __attribute__((unused)))
 
3429
com_rehash(string *, const char *)
3410
3430
{
3411
3431
  build_completion_hash(1, 0);
3412
3432
  return 0;
3415
3435
 
3416
3436
 
3417
3437
static int
3418
 
com_print(string *buffer,const char *line __attribute__((unused)))
 
3438
com_print(string *buffer,const char *)
3419
3439
{
3420
3440
  tee_puts("--------------", stdout);
3421
3441
  (void) tee_fputs(buffer->c_str(), stdout);
3442
3462
      Two null bytes are needed in the end of buff to allow
3443
3463
      get_arg to find end of string the second time it's called.
3444
3464
    */
3445
 
    tmp= strmake(buff, line, sizeof(buff)-2);
 
3465
    tmp= strncpy(buff, line, sizeof(buff)-2);
3446
3466
#ifdef EXTRA_DEBUG
3447
3467
    tmp[1]= 0;
3448
3468
#endif
3474
3494
 
3475
3495
  if (connected)
3476
3496
  {
3477
 
    sprintf(buff,"Connection id:    %u",drizzle_thread_id(&drizzle));
 
3497
    sprintf(buff,"Connection id:    %u",drizzle_con_thread_id(&con));
3478
3498
    put_info(buff,INFO_INFO,0,0);
3479
3499
    sprintf(buff,"Current database: %.128s\n",
3480
3500
            current_db ? current_db : "*** NONE ***");
3484
3504
}
3485
3505
 
3486
3506
 
3487
 
static int com_source(string *buffer __attribute__((unused)), const char *line)
 
3507
static int com_source(string *, const char *line)
3488
3508
{
3489
 
  char source_name[FN_REFLEN], *end, *param;
 
3509
  char source_name[FN_REFLEN], *end;
 
3510
  const char *param;
3490
3511
  LINE_BUFFER *line_buff;
3491
3512
  int error;
3492
3513
  STATUS old_status;
3500
3521
                    INFO_ERROR, 0,0);
3501
3522
  while (my_isspace(charset_info,*param))
3502
3523
    param++;
3503
 
  end=strmake(source_name,param,sizeof(source_name)-1);
 
3524
  end= strncpy(source_name,param,sizeof(source_name)-1);
 
3525
  end+= strlen(source_name);
3504
3526
  while (end > source_name && (my_isspace(charset_info,end[-1]) ||
3505
3527
                               my_iscntrl(charset_info,end[-1])))
3506
3528
    end--;
3507
3529
  end[0]=0;
3508
3530
  unpack_filename(source_name,source_name);
3509
3531
  /* open file name */
3510
 
  if (!(sql_file = my_fopen(source_name, O_RDONLY | O_BINARY,MYF(0))))
 
3532
  if (!(sql_file = fopen(source_name, "r")))
3511
3533
  {
3512
3534
    char buff[FN_REFLEN+60];
3513
3535
    sprintf(buff,"Failed to open file '%s', error: %d", source_name,errno);
3514
3536
    return put_info(buff, INFO_ERROR, 0 ,0);
3515
3537
  }
3516
3538
 
3517
 
  if (!(line_buff=batch_readline_init(opt_max_allowed_packet+512,sql_file)))
 
3539
  if (!(line_buff=batch_readline_init(opt_max_input_line+512,sql_file)))
3518
3540
  {
3519
 
    my_fclose(sql_file,MYF(0));
 
3541
    fclose(sql_file);
3520
3542
    return put_info("Can't initialize batch_readline", INFO_ERROR, 0 ,0);
3521
3543
  }
3522
3544
 
3534
3556
  error= read_and_execute(false);
3535
3557
  // Continue as before
3536
3558
  status=old_status;
3537
 
  my_fclose(sql_file,MYF(0));
 
3559
  fclose(sql_file);
3538
3560
  batch_readline_end(line_buff);
3539
3561
  return error;
3540
3562
}
3542
3564
 
3543
3565
/* ARGSUSED */
3544
3566
static int
3545
 
com_delimiter(string *buffer __attribute__((unused)), const char *line)
 
3567
com_delimiter(string *, const char *line)
3546
3568
{
3547
3569
  char buff[256], *tmp;
3548
3570
 
3549
 
  strmake(buff, line, sizeof(buff) - 1);
 
3571
  strncpy(buff, line, sizeof(buff) - 1);
3550
3572
  tmp= get_arg(buff, 0);
3551
3573
 
3552
3574
  if (!tmp || !*tmp)
3564
3586
      return 0;
3565
3587
    }
3566
3588
  }
3567
 
  strmake(delimiter, tmp, sizeof(delimiter) - 1);
 
3589
  strncpy(delimiter, tmp, sizeof(delimiter) - 1);
3568
3590
  delimiter_length= (int)strlen(delimiter);
3569
3591
  delimiter_str= delimiter;
3570
3592
  return 0;
3572
3594
 
3573
3595
/* ARGSUSED */
3574
3596
static int
3575
 
com_use(string *buffer __attribute__((unused)), const char *line)
 
3597
com_use(string *, const char *line)
3576
3598
{
3577
3599
  char *tmp, buff[FN_REFLEN + 1];
3578
3600
  int select_db;
 
3601
  drizzle_result_st result;
 
3602
  drizzle_return_t ret;
3579
3603
 
3580
3604
  memset(buff, 0, sizeof(buff));
3581
 
  strmake(buff, line, sizeof(buff) - 1);
 
3605
  strncpy(buff, line, sizeof(buff) - 1);
3582
3606
  tmp= get_arg(buff, 0);
3583
3607
  if (!tmp || !*tmp)
3584
3608
  {
3592
3616
  */
3593
3617
  get_current_db();
3594
3618
 
3595
 
  if (!current_db || cmp_database(charset_info, current_db,tmp))
 
3619
  if (!current_db || strcmp(current_db,tmp))
3596
3620
  {
3597
3621
    if (one_database)
3598
3622
    {
3599
3623
      skip_updates= 1;
3600
 
      select_db= 0;    // don't do drizzle_select_db()
 
3624
      select_db= 0;    // don't do drizzleclient_select_db()
3601
3625
    }
3602
3626
    else
3603
 
      select_db= 2;    // do drizzle_select_db() and build_completion_hash()
 
3627
      select_db= 2;    // do drizzleclient_select_db() and build_completion_hash()
3604
3628
  }
3605
3629
  else
3606
3630
  {
3607
3631
    /*
3608
3632
      USE to the current db specified.
3609
 
      We do need to send drizzle_select_db() to make server
 
3633
      We do need to send drizzleclient_select_db() to make server
3610
3634
      update database level privileges, which might
3611
3635
      change since last USE (see bug#10979).
3612
3636
      For performance purposes, we'll skip rebuilding of completion hash.
3613
3637
    */
3614
3638
    skip_updates= 0;
3615
 
    select_db= 1;      // do only drizzle_select_db(), without completion
 
3639
    select_db= 1;      // do only drizzleclient_select_db(), without completion
3616
3640
  }
3617
3641
 
3618
3642
  if (select_db)
3623
3647
    */
3624
3648
    if (!connected && reconnect())
3625
3649
      return opt_reconnect ? -1 : 1;                        // Fatal error
3626
 
    if (drizzle_select_db(&drizzle,tmp))
 
3650
    for (bool try_again= true; try_again; try_again= false)
3627
3651
    {
3628
 
      if (drizzle_errno(&drizzle) != CR_SERVER_GONE_ERROR)
3629
 
        return put_error(&drizzle);
3630
 
 
3631
 
      if (reconnect())
3632
 
        return opt_reconnect ? -1 : 1;                      // Fatal error
3633
 
      if (drizzle_select_db(&drizzle,tmp))
3634
 
        return put_error(&drizzle);
 
3652
      if (drizzle_select_db(&con,&result,tmp,&ret) == NULL ||
 
3653
          ret != DRIZZLE_RETURN_OK)
 
3654
      {
 
3655
        if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
3656
        {
 
3657
          int error= put_error(&con, &result);
 
3658
          drizzle_result_free(&result);
 
3659
          return error;
 
3660
        }
 
3661
 
 
3662
        if (ret != DRIZZLE_RETURN_SERVER_GONE || !try_again)
 
3663
          return put_error(&con, NULL);
 
3664
 
 
3665
        if (reconnect())
 
3666
          return opt_reconnect ? -1 : 1;                      // Fatal error
 
3667
      }
 
3668
      else
 
3669
        drizzle_result_free(&result);
3635
3670
    }
3636
3671
    free(current_db);
3637
3672
    current_db= strdup(tmp);
3644
3679
}
3645
3680
 
3646
3681
static int
3647
 
com_warnings(string *buffer __attribute__((unused)),
3648
 
             const char *line __attribute__((unused)))
 
3682
com_warnings(string *, const char *)
3649
3683
{
3650
3684
  show_warnings = 1;
3651
3685
  put_info("Show warnings enabled.",INFO_INFO, 0, 0);
3653
3687
}
3654
3688
 
3655
3689
static int
3656
 
com_nowarnings(string *buffer __attribute__((unused)),
3657
 
               const char *line __attribute__((unused)))
 
3690
com_nowarnings(string *, const char *)
3658
3691
{
3659
3692
  show_warnings = 0;
3660
3693
  put_info("Show warnings disabled.",INFO_INFO, 0, 0);
3710
3743
    if (*ptr == '\\' && ptr[1]) // escaped character
3711
3744
    {
3712
3745
      // Remove the backslash
3713
 
      my_stpcpy(ptr, ptr+1);
 
3746
      strcpy(ptr, ptr+1);
3714
3747
    }
3715
3748
    else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
3716
3749
    {
3725
3758
 
3726
3759
static int
3727
3760
sql_connect(char *host,char *database,char *user,char *password,
3728
 
                 uint silent)
 
3761
                 uint32_t silent)
3729
3762
{
 
3763
  drizzle_return_t ret;
 
3764
 
3730
3765
  if (connected)
3731
3766
  {
3732
3767
    connected= 0;
3733
 
    drizzle_close(&drizzle);
 
3768
    drizzle_con_free(&con);
 
3769
    drizzle_free(&drizzle);
3734
3770
  }
3735
3771
  drizzle_create(&drizzle);
 
3772
  if (drizzle_con_add_tcp(&drizzle, &con, host, opt_drizzle_port, user,
 
3773
                          password, database, DRIZZLE_CON_NONE) == NULL)
 
3774
  {
 
3775
    (void) put_error(&con, NULL);
 
3776
    (void) fflush(stdout);
 
3777
    return 1;
 
3778
  }
 
3779
 
 
3780
/* XXX add this back in
3736
3781
  if (opt_connect_timeout)
3737
3782
  {
3738
 
    uint timeout=opt_connect_timeout;
3739
 
    drizzle_options(&drizzle,DRIZZLE_OPT_CONNECT_TIMEOUT,
 
3783
    uint32_t timeout=opt_connect_timeout;
 
3784
    drizzleclient_options(&drizzle,DRIZZLE_OPT_CONNECT_TIMEOUT,
3740
3785
                  (char*) &timeout);
3741
3786
  }
3742
 
  if (opt_compress)
3743
 
    drizzle_options(&drizzle,DRIZZLE_OPT_COMPRESS,NULL);
3744
 
  if (opt_secure_auth)
3745
 
    drizzle_options(&drizzle, DRIZZLE_SECURE_AUTH, (char *) &opt_secure_auth);
3746
 
  if (using_opt_local_infile)
3747
 
    drizzle_options(&drizzle,DRIZZLE_OPT_LOCAL_INFILE, (char*) &opt_local_infile);
 
3787
*/
 
3788
 
 
3789
/* XXX Do we need this?
3748
3790
  if (safe_updates)
3749
3791
  {
3750
3792
    char init_command[100];
3751
3793
    sprintf(init_command,
3752
3794
            "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%"PRIu32
3753
 
            ",SQL_MAX_JOIN_SIZE=%"PRIu32,
 
3795
            ",MAX_JOIN_SIZE=%"PRIu32,
3754
3796
            select_limit, max_join_size);
3755
 
    drizzle_options(&drizzle, DRIZZLE_INIT_COMMAND, init_command);
 
3797
    drizzleclient_options(&drizzle, DRIZZLE_INIT_COMMAND, init_command);
3756
3798
  }
3757
 
  if (!drizzle_connect(&drizzle, host, user, password,
3758
 
                          database, opt_drizzle_port, opt_drizzle_unix_port,
3759
 
                          connect_flag | CLIENT_MULTI_STATEMENTS))
 
3799
*/
 
3800
  if ((ret= drizzle_con_connect(&con)) != DRIZZLE_RETURN_OK)
3760
3801
  {
3761
 
    if (!silent ||
3762
 
        (drizzle_errno(&drizzle) != CR_CONN_HOST_ERROR &&
3763
 
         drizzle_errno(&drizzle) != CR_CONNECTION_ERROR))
 
3802
    if (!silent || (ret != DRIZZLE_RETURN_GETADDRINFO &&
 
3803
                    ret != DRIZZLE_RETURN_COULD_NOT_CONNECT))
3764
3804
    {
3765
 
      (void) put_error(&drizzle);
 
3805
      (void) put_error(&con, NULL);
3766
3806
      (void) fflush(stdout);
3767
3807
      return ignore_errors ? -1 : 1;    // Abort
3768
3808
    }
3769
3809
    return -1;          // Retryable
3770
3810
  }
3771
3811
  connected=1;
 
3812
/* XXX hmm?
3772
3813
  drizzle.reconnect= debug_info_flag; // We want to know if this happens
 
3814
*/
3773
3815
  build_completion_hash(opt_rehash, 1);
3774
3816
  return 0;
3775
3817
}
3776
3818
 
3777
3819
 
3778
3820
static int
3779
 
com_status(string *buffer __attribute__((unused)),
3780
 
           const char *line __attribute__((unused)))
 
3821
com_status(string *, const char *)
3781
3822
{
 
3823
/*
3782
3824
  char buff[40];
3783
3825
  uint64_t id;
3784
 
  DRIZZLE_RES *result;
 
3826
*/
 
3827
  drizzle_result_st result;
 
3828
  drizzle_return_t ret;
3785
3829
 
3786
3830
  tee_puts("--------------", stdout);
3787
3831
  usage(1);          /* Print version */
3788
3832
  if (connected)
3789
3833
  {
3790
 
    tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",drizzle_thread_id(&drizzle));
 
3834
    tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",drizzle_con_thread_id(&con));
3791
3835
    /*
3792
3836
      Don't remove "limit 1",
3793
3837
      it is protection againts SQL_SELECT_LIMIT=0
3794
3838
    */
3795
 
    if (!drizzle_query(&drizzle,"select DATABASE(), USER() limit 1") &&
3796
 
        (result=drizzle_use_result(&drizzle)))
 
3839
    if (drizzle_query_str(&con,&result,"select DATABASE(), USER() limit 1",
 
3840
                          &ret) != NULL && ret == DRIZZLE_RETURN_OK &&
 
3841
        drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
3797
3842
    {
3798
 
      DRIZZLE_ROW cur=drizzle_fetch_row(result);
 
3843
      drizzle_row_t cur=drizzle_row_next(&result);
3799
3844
      if (cur)
3800
3845
      {
3801
3846
        tee_fprintf(stdout, "Current database:\t%s\n", cur[0] ? cur[0] : "");
3802
3847
        tee_fprintf(stdout, "Current user:\t\t%s\n", cur[1]);
3803
3848
      }
3804
 
      drizzle_free_result(result);
 
3849
      drizzle_result_free(&result);
3805
3850
    }
 
3851
    else if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
3852
      drizzle_result_free(&result);
3806
3853
    tee_puts("SSL:\t\t\tNot in use", stdout);
3807
3854
  }
3808
3855
  else
3821
3868
  tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
3822
3869
  tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
3823
3870
  tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
3824
 
  tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&drizzle));
3825
 
  tee_fprintf(stdout, "Protocol version:\t%d\n", drizzle_get_proto_info(&drizzle));
3826
 
  tee_fprintf(stdout, "Connection:\t\t%s\n", drizzle_get_host_info(&drizzle));
3827
 
  if ((id= drizzle_insert_id(&drizzle)))
 
3871
  tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&con));
 
3872
  tee_fprintf(stdout, "Protocol version:\t%d\n", drizzle_con_protocol_version(&con));
 
3873
  tee_fprintf(stdout, "Connection:\t\t%s\n", drizzle_con_host(&con));
 
3874
/* XXX need to save this from result
 
3875
  if ((id= drizzleclient_insert_id(&drizzle)))
3828
3876
    tee_fprintf(stdout, "Insert id:\t\t%s\n", llstr(id, buff));
3829
 
 
3830
 
  /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
3831
 
  if (!drizzle_query(&drizzle,"select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1") &&
3832
 
      (result=drizzle_use_result(&drizzle)))
3833
 
  {
3834
 
    DRIZZLE_ROW cur=drizzle_fetch_row(result);
3835
 
    if (cur)
3836
 
    {
3837
 
      tee_fprintf(stdout, "Server characterset:\t%s\n", cur[2] ? cur[2] : "");
3838
 
      tee_fprintf(stdout, "Db     characterset:\t%s\n", cur[3] ? cur[3] : "");
3839
 
      tee_fprintf(stdout, "Client characterset:\t%s\n", cur[0] ? cur[0] : "");
3840
 
      tee_fprintf(stdout, "Conn.  characterset:\t%s\n", cur[1] ? cur[1] : "");
3841
 
    }
3842
 
    drizzle_free_result(result);
3843
 
  }
3844
 
 
3845
 
  if (strstr(drizzle_get_host_info(&drizzle),"TCP/IP") || ! drizzle.unix_socket)
3846
 
    tee_fprintf(stdout, "TCP port:\t\t%d\n", drizzle.port);
 
3877
*/
 
3878
 
 
3879
  if (strcmp(drizzle_con_uds(&con), ""))
 
3880
    tee_fprintf(stdout, "UNIX socket:\t\t%s\n", drizzle_con_uds(&con));
3847
3881
  else
3848
 
    tee_fprintf(stdout, "UNIX socket:\t\t%s\n", drizzle.unix_socket);
3849
 
  if (drizzle.net.compress)
3850
 
    tee_fprintf(stdout, "Protocol:\t\tCompressed\n");
 
3882
    tee_fprintf(stdout, "TCP port:\t\t%d\n", drizzle_con_port(&con));
3851
3883
 
3852
3884
  if (safe_updates)
3853
3885
  {
3866
3898
}
3867
3899
 
3868
3900
static const char *
3869
 
server_version_string(DRIZZLE *con)
 
3901
server_version_string(drizzle_con_st *local_con)
3870
3902
{
3871
 
  static char buf[MAX_SERVER_VERSION_LENGTH] = "";
 
3903
  static string buf("");
 
3904
  static bool server_version_string_reserved= false;
3872
3905
 
 
3906
  if (!server_version_string_reserved)
 
3907
  {
 
3908
    buf.reserve(MAX_SERVER_VERSION_LENGTH);
 
3909
    server_version_string_reserved= true;
 
3910
  }
3873
3911
  /* Only one thread calls this, so no synchronization is needed */
3874
3912
  if (buf[0] == '\0')
3875
3913
  {
3876
 
    char *bufp = buf;
3877
 
    DRIZZLE_RES *result;
 
3914
    drizzle_result_st result;
 
3915
    drizzle_return_t ret;
3878
3916
 
3879
 
    bufp= my_stpncpy(buf, drizzle_get_server_info(con), sizeof buf);
 
3917
    buf.append(drizzle_con_server_version(local_con));
3880
3918
 
3881
3919
    /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
3882
 
    if (!drizzle_query(con, "select @@version_comment limit 1") &&
3883
 
        (result = drizzle_use_result(con)))
 
3920
    (void)drizzle_query_str(local_con, &result,
 
3921
                            "select @@version_comment limit 1", &ret);
 
3922
    if (ret == DRIZZLE_RETURN_OK &&
 
3923
        drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
3884
3924
    {
3885
 
      DRIZZLE_ROW cur = drizzle_fetch_row(result);
 
3925
      drizzle_row_t cur = drizzle_row_next(&result);
3886
3926
      if (cur && cur[0])
3887
3927
      {
3888
 
        bufp = strxnmov(bufp, sizeof buf - (bufp - buf), " ", cur[0], NULL);
 
3928
        buf.append(" ");
 
3929
        buf.append(cur[0]);
3889
3930
      }
3890
 
      drizzle_free_result(result);
 
3931
      drizzle_result_free(&result);
3891
3932
    }
3892
 
 
3893
 
    /* str*nmov doesn't guarantee NUL-termination */
3894
 
    if (bufp == buf + sizeof buf)
3895
 
      buf[sizeof buf - 1] = '\0';
 
3933
    else if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
3934
      drizzle_result_free(&result);
3896
3935
  }
3897
3936
 
3898
 
  return buf;
 
3937
  return buf.c_str();
3899
3938
}
3900
3939
 
3901
3940
static int
3902
 
put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
 
3941
put_info(const char *str,INFO_TYPE info_type, uint32_t error, const char *sqlstate)
3903
3942
{
3904
3943
  FILE *file= (info_type == INFO_ERROR ? stderr : stdout);
3905
3944
  static int inited=0;
3971
4010
 
3972
4011
 
3973
4012
static int
3974
 
put_error(DRIZZLE *con)
 
4013
put_error(drizzle_con_st *local_con, drizzle_result_st *res)
3975
4014
{
3976
 
  return put_info(drizzle_error(con), INFO_ERROR, drizzle_errno(con),
3977
 
                  drizzle_sqlstate(con));
 
4015
  const char *error;
 
4016
 
 
4017
  if (res != NULL)
 
4018
  {
 
4019
    error= drizzle_result_error(res);
 
4020
    if (!strcmp(error, ""))
 
4021
      error= drizzle_con_error(local_con);
 
4022
  }
 
4023
  else
 
4024
    error= drizzle_con_error(local_con);
 
4025
 
 
4026
  return put_info(error, INFO_ERROR,
 
4027
                  res == NULL ? drizzle_con_error_code(local_con) :
 
4028
                                drizzle_result_error_code(res),
 
4029
                  res == NULL ? drizzle_con_sqlstate(local_con) :
 
4030
                                drizzle_result_sqlstate(res));
3978
4031
}
3979
4032
 
3980
4033
 
3984
4037
  const char *end= start + (buffer->length());
3985
4038
  while (start < end && !my_isgraph(charset_info,end[-1]))
3986
4039
    end--;
3987
 
  uint pos_to_truncate= (end-start);
 
4040
  uint32_t pos_to_truncate= (end-start);
3988
4041
  if (buffer->length() > pos_to_truncate)
3989
4042
    buffer->erase(pos_to_truncate);
3990
4043
}
4058
4111
  if (sec >= 3600.0*24)
4059
4112
  {
4060
4113
    tmp=(uint32_t) floor(sec/(3600.0*24));
4061
 
    sec-=3600.0*24*tmp;
4062
 
    buff=int10_to_str((long) tmp, buff, 10);
4063
 
    buff=my_stpcpy(buff,tmp > 1 ? " days " : " day ");
 
4114
    sec-= 3600.0*24*tmp;
 
4115
    buff= int10_to_str((long) tmp, buff, 10);
 
4116
 
 
4117
    if (tmp > 1)
 
4118
      buff= strcpy(buff," days ")+6;
 
4119
    else
 
4120
      buff= strcpy(buff," day ")+5;
 
4121
 
4064
4122
  }
4065
4123
  if (sec >= 3600.0)
4066
4124
  {
4067
4125
    tmp=(uint32_t) floor(sec/3600.0);
4068
4126
    sec-=3600.0*tmp;
4069
4127
    buff=int10_to_str((long) tmp, buff, 10);
4070
 
    buff=my_stpcpy(buff,tmp > 1 ? " hours " : " hour ");
 
4128
 
 
4129
    if (tmp > 1)
 
4130
      buff= strcpy(buff, " hours ")+7;
 
4131
    else
 
4132
      buff= strcpy(buff, " hour ")+6;
4071
4133
  }
4072
4134
  if (sec >= 60.0)
4073
4135
  {
4074
4136
    tmp=(uint32_t) floor(sec/60.0);
4075
4137
    sec-=60.0*tmp;
4076
4138
    buff=int10_to_str((long) tmp, buff, 10);
4077
 
    buff=my_stpcpy(buff," min ");
 
4139
    buff= strcpy(buff," min ")+5;
4078
4140
  }
4079
4141
  if (part_second)
4080
4142
    sprintf(buff,"%.2f sec",sec);
4095
4157
  buff[0]=' ';
4096
4158
  buff[1]='(';
4097
4159
  end_timer(start_time,buff+2);
4098
 
  my_stpcpy(strchr(buff, '\0'),")");
 
4160
  strcpy(strchr(buff, '\0'),")");
4099
4161
}
4100
4162
 
4101
4163
static const char * construct_prompt()
4130
4192
        break;
4131
4193
      case 'v':
4132
4194
        if (connected)
4133
 
          processed_prompt->append(drizzle_get_server_info(&drizzle));
 
4195
          processed_prompt->append(drizzle_con_server_version(&con));
4134
4196
        else
4135
4197
          processed_prompt->append("not_connected");
4136
4198
        break;
4140
4202
      case 'h':
4141
4203
      {
4142
4204
        const char *prompt;
4143
 
        prompt= connected ? drizzle_get_host_info(&drizzle) : "not_connected";
 
4205
        prompt= connected ? drizzle_con_host(&con) : "not_connected";
4144
4206
        if (strstr(prompt, "Localhost"))
4145
4207
          processed_prompt->append("localhost");
4146
4208
        else
4159
4221
          break;
4160
4222
        }
4161
4223
 
4162
 
        const char *host_info = drizzle_get_host_info(&drizzle);
4163
 
        if (strstr(host_info, "memory"))
 
4224
        if (strcmp(drizzle_con_uds(&con), ""))
4164
4225
        {
4165
 
          processed_prompt->append(drizzle.host);
 
4226
          const char *pos=strrchr(drizzle_con_uds(&con),'/');
 
4227
          processed_prompt->append(pos ? pos+1 : drizzle_con_uds(&con));
4166
4228
        }
4167
 
        else if (strstr(host_info,"TCP/IP") ||
4168
 
                 !drizzle.unix_socket)
4169
 
          add_int_to_prompt(drizzle.port);
4170
4229
        else
4171
 
        {
4172
 
          char *pos=strrchr(drizzle.unix_socket,'/');
4173
 
          processed_prompt->append(pos ? pos+1 : drizzle.unix_socket);
4174
 
        }
 
4230
          add_int_to_prompt(drizzle_con_port(&con));
4175
4231
      }
4176
4232
      break;
4177
4233
      case 'U':
4188
4244
        break;
4189
4245
      case PROMPT_CHAR:
4190
4246
        {
4191
 
          char c= PROMPT_CHAR;
4192
 
          processed_prompt->append(&c, 1);
 
4247
          processed_prompt->append(PROMPT_CHAR, 1);
4193
4248
        }
4194
4249
        break;
4195
4250
      case 'n':
4196
4251
        {
4197
 
          char c= '\n';
4198
 
          processed_prompt->append(&c, 1);
 
4252
          processed_prompt->append('\n', 1);
4199
4253
        }
4200
4254
        break;
4201
4255
      case ' ':
4202
4256
      case '_':
4203
4257
        {
4204
 
          char c= ' ';
4205
 
          processed_prompt->append(&c, 1);
 
4258
          processed_prompt->append(' ', 1);
4206
4259
        }
4207
4260
        break;
4208
4261
      case 'R':
4286
4339
 
4287
4340
static void init_username()
4288
4341
{
 
4342
/* XXX need this?
4289
4343
  free(full_username);
4290
4344
  free(part_username);
4291
4345
 
4292
 
  DRIZZLE_RES *result;
4293
 
  if (!drizzle_query(&drizzle,"select USER()") &&
4294
 
      (result=drizzle_use_result(&drizzle)))
 
4346
  drizzle_result_st *result;
 
4347
  if (!drizzleclient_query(&drizzle,"select USER()") &&
 
4348
      (result=drizzleclient_use_result(&drizzle)))
4295
4349
  {
4296
 
    DRIZZLE_ROW cur=drizzle_fetch_row(result);
 
4350
    drizzle_row_t cur=drizzleclient_fetch_row(result);
4297
4351
    full_username= strdup(cur[0]);
4298
4352
    part_username= strdup(strtok(cur[0],"@"));
4299
 
    (void) drizzle_fetch_row(result);        // Read eof
 
4353
    (void) drizzleclient_fetch_row(result);        // Read eof
4300
4354
  }
 
4355
*/
4301
4356
}
4302
4357
 
4303
 
static int com_prompt(string *buffer __attribute__((unused)),
4304
 
                      const char *line)
 
4358
static int com_prompt(string *, const char *line)
4305
4359
{
4306
 
  char *ptr=strchr(line, ' ');
4307
 
  prompt_counter = 0;
4308
 
  free(current_prompt);
4309
 
  current_prompt= strdup(ptr ? ptr+1 : default_prompt);
4310
 
  if (!ptr)
 
4360
  const char *ptr=strchr(line, ' ');
 
4361
  if (ptr == NULL)
4311
4362
    tee_fprintf(stdout, "Returning to default PROMPT of %s\n",
4312
4363
                default_prompt);
 
4364
  prompt_counter = 0;
 
4365
  char * tmpptr= strdup(ptr ? ptr+1 : default_prompt);
 
4366
  if (tmpptr == NULL)
 
4367
    tee_fprintf(stdout, "Memory allocation error. Not changing prompt\n");
4313
4368
  else
 
4369
  {
 
4370
    free(current_prompt);
 
4371
    current_prompt= tmpptr;
4314
4372
    tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
 
4373
  }
4315
4374
  return 0;
4316
4375
}
4317
4376