~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzle.cc

Merged in latest plugin-slot-reorg.

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
 
#include "my_readline.h"
 
41
#include "client/linebuffer.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 <map>
132
132
 
133
133
using namespace std;
134
134
 
 
135
const string VER("14.14");
 
136
/* Don't try to make a nice table if the data is too big */
 
137
const uint32_t MAX_COLUMN_LENGTH= 1024;
 
138
 
 
139
/* Buffer to hold 'version' and 'version_comment' */
 
140
const int MAX_SERVER_VERSION_LENGTH= 128;
 
141
 
135
142
#define PROMPT_CHAR '\\'
136
143
#define DEFAULT_DELIMITER ";"
137
144
 
140
147
  int exit_status;
141
148
  uint32_t query_start_line;
142
149
  char *file_name;
143
 
  LINE_BUFFER *line_buff;
 
150
  LineBuffer *line_buff;
144
151
  bool batch,add_to_history;
145
152
} STATUS;
146
153
 
147
154
 
148
 
static HashTable ht;
 
155
static map<string, string>::iterator completion_iter;
 
156
static map<string, string>::iterator completion_end;
 
157
static map<string, string> completion_map;
 
158
static string completion_string;
 
159
 
149
160
static char **defaults_argv;
150
161
 
151
162
enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
152
163
typedef enum enum_info_type INFO_TYPE;
153
164
 
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;
 
165
static drizzle_st drizzle;      /* The library handle */
 
166
static drizzle_con_st con;      /* The connection */
 
167
static bool ignore_errors= false, quick= false,
 
168
  connected= false, opt_raw_data= false, unbuffered= false,
 
169
  output_tables= false, opt_rehash= true, skip_updates= false,
 
170
  safe_updates= false, one_database= false,
 
171
  opt_compress= false, opt_shutdown= false, opt_ping= false,
 
172
  vertical= false, line_numbers= true, column_names= true,
 
173
  opt_nopager= true, opt_outfile= false, named_cmds= false,
 
174
  tty_password= false, opt_nobeep= false, opt_reconnect= true,
 
175
  default_charset_used= false, opt_secure_auth= false,
 
176
  default_pager_set= false, opt_sigint_ignore= false,
 
177
  auto_vertical_output= false,
 
178
  show_warnings= false, executing_query= false, interrupted_query= false;
 
179
static uint32_t  show_progress_size= 0;
166
180
static bool debug_info_flag, debug_check_flag;
167
181
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;
 
182
static bool preserve_comments= false;
 
183
static uint32_t opt_max_input_line, opt_drizzle_port= 0;
 
184
static int verbose= 0, opt_silent= 0, opt_local_infile= 0;
 
185
static uint32_t my_end_arg;
 
186
static char * opt_drizzle_unix_port= NULL;
 
187
static drizzle_capabilities_t connect_flag= DRIZZLE_CAPABILITIES_NONE;
 
188
static char *current_host, *current_db, *current_user= NULL,
 
189
  *opt_password= NULL, *delimiter_str= NULL, *current_prompt= NULL;
176
190
static char *histfile;
177
191
static char *histfile_tmp;
178
192
static string *glob_buffer;
179
193
static string *processed_prompt= NULL;
180
194
static char *default_prompt= NULL;
181
 
static char *full_username=0,*part_username=0;
 
195
static char *full_username= NULL,*part_username= NULL;
182
196
static STATUS status;
183
197
static uint32_t select_limit;
184
198
static uint32_t max_join_size;
185
199
static uint32_t opt_connect_timeout= 0;
186
 
static char drizzle_charsets_dir[FN_REFLEN+1];
187
200
// 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",
 
201
static const char *day_names[]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
 
202
static const char *month_names[]= {"Jan","Feb","Mar","Apr","May","Jun","Jul",
190
203
                                  "Aug","Sep","Oct","Nov","Dec"};
191
204
static char default_pager[FN_REFLEN];
192
205
static char pager[FN_REFLEN], outfile[FN_REFLEN];
193
206
static FILE *PAGER, *OUTFILE;
194
 
static MEM_ROOT hash_mem_root;
195
 
static uint prompt_counter;
 
207
static uint32_t prompt_counter;
196
208
static char delimiter[16]= DEFAULT_DELIMITER;
197
 
static uint delimiter_length= 1;
 
209
static uint32_t delimiter_length= 1;
198
210
unsigned short terminal_width= 80;
199
211
 
200
212
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
201
213
 
202
 
int drizzle_real_query_for_lazy(const char *buf, int length);
203
 
int drizzle_store_result_for_lazy(DRIZZLE_RES **result);
 
214
int drizzleclient_real_query_for_lazy(const char *buf, int length,
 
215
                                      drizzle_result_st *result,
 
216
                                      uint32_t *error_code);
 
217
int drizzleclient_store_result_for_lazy(drizzle_result_st *result);
204
218
 
205
219
 
206
220
void tee_fprintf(FILE *file, const char *fmt, ...);
210
224
static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
211
225
/* The names of functions that actually do the manipulation. */
212
226
static int get_options(int argc,char **argv);
213
 
bool get_one_option(int optid, const struct my_option *opt,
214
 
                    char *argument);
 
227
extern "C" bool get_one_option(int optid, const struct my_option *opt,
 
228
                               char *argument);
215
229
static int com_quit(string *str,const char*),
216
230
  com_go(string *str,const char*), com_ego(string *str,const char*),
217
231
  com_print(string *str,const char*),
226
240
 
227
241
static int read_and_execute(bool interactive);
228
242
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,
 
243
                       uint32_t silent);
 
244
static const char *server_version_string(drizzle_con_st *con);
 
245
static int put_info(const char *str,INFO_TYPE info,uint32_t error,
232
246
                    const char *sql_state);
233
 
static int put_error(DRIZZLE *drizzle);
 
247
static int put_error(drizzle_con_st *con, drizzle_result_st *res);
234
248
static void safe_put_field(const char *pos,uint32_t length);
235
249
static void init_pager(void);
236
250
static void end_pager(void);
240
254
static char *get_arg(char *line, bool get_next_arg);
241
255
static void init_username(void);
242
256
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);
 
257
static int get_result_width(drizzle_result_st *res);
 
258
static int get_field_disp_length(drizzle_column_st * field);
245
259
static const char * strcont(register const char *str, register const char *set);
246
260
 
247
261
/* A structure which contains information on the commands this program
256
270
 
257
271
 
258
272
static COMMANDS commands[] = {
259
 
  { "?",      '?', com_help,   1, N_("Synonym for `help'.") },
 
273
  { "?",      '?', com_help,   0, N_("Synonym for `help'.") },
260
274
  { "clear",  'c', com_clear,  0, N_("Clear command.")},
261
275
  { "connect",'r', com_connect,1,
262
 
    N_("Reconnect to the server. Optional arguments are db and host." }),
 
276
    N_("Reconnect to the server. Optional arguments are db and host.")},
263
277
  { "delimiter", 'd', com_delimiter,    1,
264
278
    N_("Set statement delimiter. NOTE: Takes the rest of the line as new delimiter.") },
265
279
  { "ego",    'G', com_ego,    0,
266
280
    N_("Send command to drizzle server, display result vertically.")},
267
281
  { "exit",   'q', com_quit,   0, N_("Exit drizzle. Same as quit.")},
268
282
  { "go",     'g', com_go,     0, N_("Send command to drizzle server.") },
269
 
  { "help",   'h', com_help,   1, N_("Display this help.") },
 
283
  { "help",   'h', com_help,   0, N_("Display this help.") },
270
284
  { "nopager",'n', com_nopager,0, N_("Disable pager, print to stdout.") },
271
285
  { "notee",  't', com_notee,  0, N_("Don't write into outfile.") },
272
286
  { "pager",  'P', com_pager,  1,
372
386
  { "CROSS", 0, 0, 0, ""},
373
387
  { "CUBE", 0, 0, 0, ""},
374
388
  { "CURRENT_DATE", 0, 0, 0, ""},
375
 
  { "CURRENT_TIME", 0, 0, 0, ""},
376
389
  { "CURRENT_TIMESTAMP", 0, 0, 0, ""},
377
390
  { "CURRENT_USER", 0, 0, 0, ""},
378
391
  { "CURSOR", 0, 0, 0, ""},
451
464
  { "FULL", 0, 0, 0, ""},
452
465
  { "FULLTEXT", 0, 0, 0, ""},
453
466
  { "FUNCTION", 0, 0, 0, ""},
454
 
  { "GET_FORMAT", 0, 0, 0, ""},
455
467
  { "GLOBAL", 0, 0, 0, ""},
456
468
  { "GRANT", 0, 0, 0, ""},
457
469
  { "GRANTS", 0, 0, 0, ""},
513
525
  { "LINESTRING", 0, 0, 0, ""},
514
526
  { "LOAD", 0, 0, 0, ""},
515
527
  { "LOCAL", 0, 0, 0, ""},
516
 
  { "LOCALTIME", 0, 0, 0, ""},
517
528
  { "LOCALTIMESTAMP", 0, 0, 0, ""},
518
529
  { "LOCK", 0, 0, 0, ""},
519
530
  { "LOCKS", 0, 0, 0, ""},
610
621
  { "QUARTER", 0, 0, 0, ""},
611
622
  { "QUERY", 0, 0, 0, ""},
612
623
  { "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
624
  { "READ", 0, 0, 0, ""},
618
625
  { "READS", 0, 0, 0, ""},
619
626
  { "REAL", 0, 0, 0, ""},
715
722
  { "TERMINATED", 0, 0, 0, ""},
716
723
  { "TEXT", 0, 0, 0, ""},
717
724
  { "THEN", 0, 0, 0, ""},
718
 
  { "TIME", 0, 0, 0, ""},
719
725
  { "TIMESTAMP", 0, 0, 0, ""},
720
726
  { "TIMESTAMPADD", 0, 0, 0, ""},
721
727
  { "TIMESTAMPDIFF", 0, 0, 0, ""},
749
755
  { "USE_FRM", 0, 0, 0, ""},
750
756
  { "USING", 0, 0, 0, ""},
751
757
  { "UTC_DATE", 0, 0, 0, ""},
752
 
  { "UTC_TIME", 0, 0, 0, ""},
753
758
  { "UTC_TIMESTAMP", 0, 0, 0, ""},
754
759
  { "VALUE", 0, 0, 0, ""},
755
760
  { "VALUES", 0, 0, 0, ""},
776
781
  { "ABS", 0, 0, 0, ""},
777
782
  { "ACOS", 0, 0, 0, ""},
778
783
  { "ADDDATE", 0, 0, 0, ""},
779
 
  { "ADDTIME", 0, 0, 0, ""},
780
784
  { "AES_ENCRYPT", 0, 0, 0, ""},
781
785
  { "AES_DECRYPT", 0, 0, 0, ""},
782
786
  { "AREA", 0, 0, 0, ""},
789
793
  { "ATAN2", 0, 0, 0, ""},
790
794
  { "BENCHMARK", 0, 0, 0, ""},
791
795
  { "BIN", 0, 0, 0, ""},
792
 
  { "BIT_COUNT", 0, 0, 0, ""},
793
796
  { "BIT_OR", 0, 0, 0, ""},
794
797
  { "BIT_AND", 0, 0, 0, ""},
795
798
  { "BIT_XOR", 0, 0, 0, ""},
796
799
  { "CAST", 0, 0, 0, ""},
797
800
  { "CEIL", 0, 0, 0, ""},
798
801
  { "CEILING", 0, 0, 0, ""},
799
 
  { "BIT_LENGTH", 0, 0, 0, ""},
800
802
  { "CENTROID", 0, 0, 0, ""},
801
803
  { "CHAR_LENGTH", 0, 0, 0, ""},
802
804
  { "CHARACTER_LENGTH", 0, 0, 0, ""},
814
816
  { "CRC32", 0, 0, 0, ""},
815
817
  { "CROSSES", 0, 0, 0, ""},
816
818
  { "CURDATE", 0, 0, 0, ""},
817
 
  { "CURTIME", 0, 0, 0, ""},
818
819
  { "DATE_ADD", 0, 0, 0, ""},
819
820
  { "DATEDIFF", 0, 0, 0, ""},
820
821
  { "DATE_FORMAT", 0, 0, 0, ""},
884
885
  { "LTRIM", 0, 0, 0, ""},
885
886
  { "MAKE_SET", 0, 0, 0, ""},
886
887
  { "MAKEDATE", 0, 0, 0, ""},
887
 
  { "MAKETIME", 0, 0, 0, ""},
888
888
  { "MASTER_POS_WAIT", 0, 0, 0, ""},
889
889
  { "MAX", 0, 0, 0, ""},
890
890
  { "MBRCONTAINS", 0, 0, 0, ""},
941
941
  { "ROW_COUNT", 0, 0, 0, ""},
942
942
  { "RPAD", 0, 0, 0, ""},
943
943
  { "RTRIM", 0, 0, 0, ""},
944
 
  { "SEC_TO_TIME", 0, 0, 0, ""},
945
944
  { "SESSION_USER", 0, 0, 0, ""},
946
945
  { "SUBDATE", 0, 0, 0, ""},
947
946
  { "SIGN", 0, 0, 0, ""},
963
962
  { "SUBSTR", 0, 0, 0, ""},
964
963
  { "SUBSTRING", 0, 0, 0, ""},
965
964
  { "SUBSTRING_INDEX", 0, 0, 0, ""},
966
 
  { "SUBTIME", 0, 0, 0, ""},
967
965
  { "SUM", 0, 0, 0, ""},
968
966
  { "SYSDATE", 0, 0, 0, ""},
969
967
  { "SYSTEM_USER", 0, 0, 0, ""},
970
968
  { "TAN", 0, 0, 0, ""},
971
969
  { "TIME_FORMAT", 0, 0, 0, ""},
972
 
  { "TIME_TO_SEC", 0, 0, 0, ""},
973
 
  { "TIMEDIFF", 0, 0, 0, ""},
974
970
  { "TO_DAYS", 0, 0, 0, ""},
975
971
  { "TOUCHES", 0, 0, 0, ""},
976
972
  { "TRIM", 0, 0, 0, ""},
1007
1003
static bool add_line(string *buffer,char *line,char *in_string,
1008
1004
                     bool *ml_comment);
1009
1005
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);
 
1006
static void print_table_data(drizzle_result_st *result);
 
1007
static void print_tab_data(drizzle_result_st *result);
 
1008
static void print_table_data_vertically(drizzle_result_st *result);
 
1009
static void print_warnings(uint32_t error_code);
1014
1010
static uint32_t start_timer(void);
1015
1011
static void end_timer(uint32_t start_time,char *buff);
1016
1012
static void drizzle_end_timer(uint32_t start_time,char *buff);
1017
1013
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);
 
1014
extern "C" void drizzle_end(int sig);
 
1015
extern "C" void handle_sigint(int sig);
1020
1016
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1021
 
static RETSIGTYPE window_resize(int sig);
 
1017
static void window_resize(int sig);
1022
1018
#endif
1023
1019
 
 
1020
static inline int is_prefix(const char *s, const char *t)
 
1021
{
 
1022
  while (*t)
 
1023
    if (*s++ != *t++) return 0;
 
1024
  return 1;                                     /* WRONG */
 
1025
}
 
1026
 
 
1027
/**
 
1028
  Shutdown the server that we are currently connected to.
 
1029
 
 
1030
  @retval
 
1031
    true success
 
1032
  @retval
 
1033
    false failure
 
1034
*/
 
1035
static bool server_shutdown(void)
 
1036
{
 
1037
  drizzle_result_st result;
 
1038
  drizzle_return_t ret;
 
1039
 
 
1040
  if (verbose)
 
1041
  {
 
1042
    printf("shutting down drizzled");
 
1043
    if (opt_drizzle_port > 0)
 
1044
      printf(" on port %d", opt_drizzle_port);
 
1045
    printf("... ");
 
1046
  }
 
1047
 
 
1048
  if (drizzle_shutdown(&con, &result, DRIZZLE_SHUTDOWN_DEFAULT,
 
1049
                       &ret) == NULL || ret != DRIZZLE_RETURN_OK)
 
1050
  {
 
1051
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
1052
    {
 
1053
      fprintf(stderr, "shutdown failed; error: '%s'",
 
1054
              drizzle_result_error(&result));
 
1055
      drizzle_result_free(&result);
 
1056
    }
 
1057
    else
 
1058
    {
 
1059
      fprintf(stderr, "shutdown failed; error: '%s'",
 
1060
              drizzle_con_error(&con));
 
1061
    }
 
1062
    return false;
 
1063
  }
 
1064
 
 
1065
  drizzle_result_free(&result);
 
1066
 
 
1067
  if (verbose)
 
1068
    printf("done\n");
 
1069
 
 
1070
  return true;
 
1071
}
 
1072
 
 
1073
/**
 
1074
  Ping the server that we are currently connected to.
 
1075
 
 
1076
  @retval
 
1077
    true success
 
1078
  @retval
 
1079
    false failure
 
1080
*/
 
1081
static bool server_ping(void)
 
1082
{
 
1083
  drizzle_result_st result;
 
1084
  drizzle_return_t ret;
 
1085
 
 
1086
  if (drizzle_ping(&con, &result, &ret) != NULL && ret == DRIZZLE_RETURN_OK)
 
1087
  {
 
1088
    if (opt_silent < 2)
 
1089
      printf("drizzled is alive\n");
 
1090
  }
 
1091
  else
 
1092
  {
 
1093
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
1094
    {
 
1095
      fprintf(stderr, "ping failed; error: '%s'",
 
1096
              drizzle_result_error(&result));
 
1097
      drizzle_result_free(&result);
 
1098
    }
 
1099
    else
 
1100
    {
 
1101
      fprintf(stderr, "drizzled won't answer to ping, error: '%s'",
 
1102
              drizzle_con_error(&con));
 
1103
    }
 
1104
    return false;
 
1105
  }
 
1106
  drizzle_result_free(&result);
 
1107
  return true;
 
1108
}
 
1109
 
 
1110
/**
 
1111
  Execute command(s) specified by the user.
 
1112
 
 
1113
  @param error  error status of command execution.
 
1114
                If an error had occurred, this variable will be set
 
1115
                to 1 whereas on success, it shall be set to 0. This
 
1116
                value will be supplied to the exit() function used
 
1117
                by the caller.
 
1118
 
 
1119
  @retval
 
1120
    false no commands were executed
 
1121
  @retval
 
1122
    true  at least one command was executed
 
1123
*/
 
1124
static bool execute_commands(int *error)
 
1125
{
 
1126
  bool executed= false;
 
1127
  *error= 0;
 
1128
 
 
1129
  if (opt_ping)
 
1130
  {
 
1131
    if (server_ping() == false)
 
1132
      *error= 1;
 
1133
    executed= true;
 
1134
  }
 
1135
 
 
1136
  if (opt_shutdown)
 
1137
  {
 
1138
    if (server_shutdown() == false)
 
1139
      *error= 1;
 
1140
    executed= true;
 
1141
  }
 
1142
  return executed;
 
1143
}
 
1144
 
1024
1145
int main(int argc,char *argv[])
1025
1146
{
1026
 
  char buff[80];
1027
 
 
1028
1147
#if defined(ENABLE_NLS)
1029
1148
# if defined(HAVE_LOCALE_H)
1030
1149
  setlocale(LC_ALL, "");
1035
1154
 
1036
1155
  MY_INIT(argv[0]);
1037
1156
  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));
 
1157
  default_prompt= strdup(getenv("DRIZZLE_PS1") ?
 
1158
                         getenv("DRIZZLE_PS1") :
 
1159
                         "drizzle> ");
 
1160
  
 
1161
  if (default_prompt == NULL)
 
1162
  {
 
1163
    fprintf(stderr, _("Memory allocation error while constructing initial "
 
1164
                      "prompt. Aborting.\n"));
 
1165
    exit(ENOMEM);
 
1166
  }
 
1167
  current_prompt= strdup(default_prompt);
 
1168
  if (current_prompt == NULL)
 
1169
  {
 
1170
    fprintf(stderr, _("Memory allocation error while constructing initial "
 
1171
                      "prompt. Aborting.\n"));
 
1172
    exit(ENOMEM);
 
1173
  }
1042
1174
  processed_prompt= new string();
1043
1175
  processed_prompt->reserve(32);
1044
1176
 
1045
1177
  prompt_counter=0;
1046
1178
 
1047
1179
  outfile[0]=0;      // no (default) outfile
1048
 
  my_stpcpy(pager, "stdout");  // the default, if --pager wasn't given
 
1180
  strcpy(pager, "stdout");  // the default, if --pager wasn't given
1049
1181
  {
1050
1182
    char *tmp=getenv("PAGER");
1051
1183
    if (tmp && strlen(tmp))
1052
1184
    {
1053
1185
      default_pager_set= 1;
1054
 
      my_stpcpy(default_pager, tmp);
 
1186
      strcpy(default_pager, tmp);
1055
1187
    }
1056
1188
  }
1057
1189
  if (!isatty(0) || !isatty(1))
1077
1209
      close(stdout_fileno_copy);             /* Clean up dup(). */
1078
1210
  }
1079
1211
 
1080
 
  load_defaults("my",load_default_groups,&argc,&argv);
 
1212
  load_defaults("drizzle",load_default_groups,&argc,&argv);
1081
1213
  defaults_argv=argv;
1082
1214
  if (get_options(argc, (char **) argv))
1083
1215
  {
1085
1217
    my_end(0);
1086
1218
    exit(1);
1087
1219
  }
1088
 
  if (status.batch && !status.line_buff &&
1089
 
      !(status.line_buff=batch_readline_init(opt_max_allowed_packet+512,stdin)))
1090
 
  {
1091
 
    free_defaults(defaults_argv);
1092
 
    my_end(0);
1093
 
    exit(1);
1094
 
  }
1095
 
  completion_hash_init(&ht, 128);
1096
 
  init_alloc_root(&hash_mem_root, 16384, 0);
 
1220
 
1097
1221
  memset(&drizzle, 0, sizeof(drizzle));
1098
1222
  if (sql_connect(current_host,current_db,current_user,opt_password,
1099
1223
                  opt_silent))
1102
1226
    status.exit_status= 1;
1103
1227
    drizzle_end(-1);
1104
1228
  }
 
1229
 
 
1230
  int command_error;
 
1231
  if (execute_commands(&command_error) != false)
 
1232
  {
 
1233
    /* we've executed a command so exit before we go into readline mode */
 
1234
    free_defaults(defaults_argv);
 
1235
    my_end(0);
 
1236
    exit(command_error);
 
1237
  }
 
1238
 
 
1239
  if (status.batch && !status.line_buff)
 
1240
  {
 
1241
    status.line_buff= new(std::nothrow) LineBuffer(opt_max_input_line, stdin);
 
1242
    if (status.line_buff == NULL)
 
1243
    {
 
1244
      free_defaults(defaults_argv);
 
1245
      my_end(0);
 
1246
      exit(1);
 
1247
    }
 
1248
  }
 
1249
 
1105
1250
  if (!status.batch)
1106
1251
    ignore_errors=1;        // Don't abort monitor
1107
1252
 
1123
1268
 
1124
1269
  glob_buffer= new string();
1125
1270
  glob_buffer->reserve(512);
1126
 
  
 
1271
 
1127
1272
  char * output_buff= (char *)malloc(512);
1128
1273
  memset(output_buff, '\0', 512);
1129
1274
 
1130
1275
  sprintf(output_buff,
1131
1276
          _("Your Drizzle connection id is %u\nServer version: %s\n"),
1132
 
          drizzle_thread_id(&drizzle),
1133
 
          server_version_string(&drizzle));
 
1277
          drizzle_con_thread_id(&con),
 
1278
          server_version_string(&con));
1134
1279
  put_info(output_buff, INFO_INFO, 0, 0);
1135
1280
 
1136
1281
  initialize_readline(current_prompt);
1141
1286
      histfile= strdup(getenv("DRIZZLE_HISTFILE"));
1142
1287
    else if (getenv("HOME"))
1143
1288
    {
1144
 
      histfile=(char*) my_malloc((uint) strlen(getenv("HOME"))
1145
 
                                 + (uint) strlen("/.drizzle_history")+2,
1146
 
                                 MYF(MY_WME));
 
1289
      histfile=(char*) malloc(strlen(getenv("HOME")) + strlen("/.drizzle_history") + 2);
1147
1290
      if (histfile)
1148
1291
        sprintf(histfile,"%s/.drizzle_history",getenv("HOME"));
1149
1292
      char link_name[FN_REFLEN];
1150
 
      if (my_readlink(link_name, histfile, 0) == 0 &&
1151
 
          strncmp(link_name, "/dev/null", 10) == 0)
 
1293
      ssize_t sym_link_size= readlink(histfile,link_name,FN_REFLEN-1);
 
1294
      if (sym_link_size >= 0)
1152
1295
      {
1153
 
        /* The .drizzle_history file is a symlink to /dev/null, don't use it */
1154
 
        free(histfile);
1155
 
        histfile= 0;
 
1296
        link_name[sym_link_size]= '\0';
 
1297
        if (strncmp(link_name, "/dev/null", 10) == 0)
 
1298
        {
 
1299
          /* The .drizzle_history file is a symlink to /dev/null, don't use it */
 
1300
          free(histfile);
 
1301
          histfile= 0;
 
1302
        }
1156
1303
      }
1157
1304
    }
1158
1305
    if (histfile)
1160
1307
      if (verbose)
1161
1308
        tee_fprintf(stdout, _("Reading history-file %s\n"),histfile);
1162
1309
      read_history(histfile);
1163
 
      if (!(histfile_tmp= (char*) my_malloc((uint) strlen(histfile) + 5,
1164
 
                                            MYF(MY_WME))))
 
1310
      if (!(histfile_tmp= (char*) malloc((uint32_t) strlen(histfile) + 5)))
1165
1311
      {
1166
1312
        fprintf(stderr, _("Couldn't allocate memory for temp histfile!\n"));
1167
1313
        exit(1);
1169
1315
      sprintf(histfile_tmp, "%s.TMP", histfile);
1170
1316
    }
1171
1317
  }
1172
 
  sprintf(buff, "%s",
1173
 
          _("Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n"));
1174
1318
 
1175
 
  put_info(buff,INFO_INFO,0,0);
 
1319
  put_info(_("Type 'help;' or '\\h' for help. "
 
1320
             "Type '\\c' to clear the buffer.\n"),INFO_INFO,0,0);
1176
1321
  status.exit_status= read_and_execute(!status.batch);
1177
1322
  if (opt_outfile)
1178
1323
    end_tee();
1181
1326
  return(0);        // Keep compiler happy
1182
1327
}
1183
1328
 
1184
 
RETSIGTYPE drizzle_end(int sig)
 
1329
void drizzle_end(int sig)
1185
1330
{
1186
 
  drizzle_close(&drizzle);
 
1331
  drizzle_con_free(&con);
 
1332
  drizzle_free(&drizzle);
1187
1333
  if (!status.batch && !quick && histfile)
1188
1334
  {
1189
1335
    /* write-history */
1192
1338
    if (!write_history(histfile_tmp))
1193
1339
      my_rename(histfile_tmp, histfile, MYF(MY_WME));
1194
1340
  }
1195
 
  batch_readline_end(status.line_buff);
1196
 
  completion_hash_free(&ht);
1197
 
  free_root(&hash_mem_root,MYF(0));
 
1341
  delete status.line_buff;
 
1342
  status.line_buff= 0;
1198
1343
 
1199
1344
  if (sig >= 0)
1200
1345
    put_info(sig ? _("Aborted") : _("Bye"), INFO_RESULT,0,0);
1224
1369
  If query is in process, kill query
1225
1370
  no query in process, terminate like previous behavior
1226
1371
*/
1227
 
RETSIGTYPE handle_sigint(int sig)
 
1372
extern "C"
 
1373
void handle_sigint(int sig)
1228
1374
{
1229
1375
  char kill_buffer[40];
1230
 
  DRIZZLE *kill_drizzle= NULL;
 
1376
  drizzle_con_st kill_drizzle;
 
1377
  drizzle_result_st res;
 
1378
  drizzle_return_t ret;
1231
1379
 
1232
1380
  /* terminate if no query being executed, or we already tried interrupting */
1233
1381
  if (!executing_query || interrupted_query) {
1234
1382
    goto err;
1235
1383
  }
1236
1384
 
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))
 
1385
  if (drizzle_con_add_tcp(&drizzle, &kill_drizzle, current_host,
 
1386
                          opt_drizzle_port, current_user, opt_password, NULL,
 
1387
                          DRIZZLE_CON_NONE) == NULL)
1240
1388
  {
1241
1389
    goto err;
1242
1390
  }
1243
1391
 
1244
1392
  /* 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);
 
1393
  sprintf(kill_buffer, "KILL /*!50000 QUERY */ %u",
 
1394
          drizzle_con_thread_id(&con));
 
1395
 
 
1396
  if (drizzle_query_str(&kill_drizzle, &res, kill_buffer, &ret) != NULL)
 
1397
    drizzle_result_free(&res);
 
1398
 
 
1399
  drizzle_con_free(&kill_drizzle);
1248
1400
  tee_fprintf(stdout, _("Query aborted by Ctrl+C\n"));
1249
1401
 
1250
1402
  interrupted_query= 1;
1257
1409
 
1258
1410
 
1259
1411
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1260
 
RETSIGTYPE window_resize(int sig __attribute__((unused)))
 
1412
void window_resize(int)
1261
1413
{
1262
1414
  struct winsize window_size;
1263
1415
 
1277
1429
   (char**) &opt_rehash, (char**) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
1278
1430
   0, 0},
1279
1431
  {"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."),
 
1432
   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
1433
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1282
1434
  {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
1283
1435
   N_("Automatically switch to vertical output mode if the result is wider than the terminal width."),
1284
1436
   (char**) &auto_vertical_output, (char**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1285
1437
  {"batch", 'B',
1286
1438
   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
1439
  {"column-type-info", OPT_COLUMN_TYPES, N_("Display column type information."),
1291
1440
   (char**) &column_types_flag, (char**) &column_types_flag,
1292
1441
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1360
1509
  {"no-pager", OPT_NOPAGER,
1361
1510
   N_("Disable pager and print to stdout. See interactive help (\\h) also. WARNING: option deprecated; use --disable-pager instead."),
1362
1511
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1363
 
  {"password", 'p',
 
1512
  {"password", 'P',
1364
1513
   N_("Password to use when connecting to server. If password is not given it's asked from the tty."),
1365
1514
   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, ")
 
1515
  {"port", 'p', N_("Port number to use for connection or 0 for default to, in order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, ")
1367
1516
   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},
 
1517
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1370
1518
  {"prompt", OPT_PROMPT, N_("Set the drizzle prompt to this value."),
1371
1519
   (char**) &current_prompt, (char**) &current_prompt, 0, GET_STR_ALLOC,
1372
1520
   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
1521
  {"quick", 'q',
1376
1522
   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
1523
   (char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1380
1526
   0, 0, 0},
1381
1527
  {"reconnect", OPT_RECONNECT, N_("Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default."),
1382
1528
   (char**) &opt_reconnect, (char**) &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
 
1529
  {"shutdown", OPT_SHUTDOWN, N_("Shutdown the server."),
 
1530
   (char**) &opt_shutdown, (char**) &opt_shutdown, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1383
1531
  {"silent", 's', N_("Be more silent. Print results with a tab as separator, each row on new line."), 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
1384
1532
   0, 0},
1385
1533
  {"socket", 'S', N_("Socket file to use for connection."),
1392
1540
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1393
1541
  {"no-tee", OPT_NOTEE, N_("Disable outfile. See interactive help (\\h) also. WARNING: option deprecated; use --disable-tee instead"), 0, 0, 0, GET_NO_ARG,
1394
1542
   NO_ARG, 0, 0, 0, 0, 0, 0},
1395
 
#ifndef DONT_ALLOW_USER_CHANGE
1396
1543
  {"user", 'u', N_("User for login if not current user."), (char**) &current_user,
1397
1544
   (char**) &current_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1398
 
#endif
1399
1545
  {"safe-updates", 'U', N_("Only allow UPDATE and DELETE that uses keys."),
1400
1546
   (char**) &safe_updates, (char**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
1401
1547
   0, 0, 0, 0},
1411
1557
  {"connect_timeout", OPT_CONNECT_TIMEOUT,
1412
1558
   N_("Number of seconds before connection timeout."),
1413
1559
   (char**) &opt_connect_timeout,
1414
 
   (char**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0,
 
1560
   (char**) &opt_connect_timeout, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 3600*12, 0,
1415
1561
   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,
 
1562
  {"max_input_line", OPT_MAX_INPUT_LINE,
 
1563
   N_("Max length of input line"),
 
1564
   (char**) &opt_max_input_line, (char**) &opt_max_input_line, 0,
 
1565
   GET_UINT32, REQUIRED_ARG, 16 *1024L*1024L, 4096,
1420
1566
   (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
1567
  {"select_limit", OPT_SELECT_LIMIT,
1426
1568
   N_("Automatic limit for SELECT when using --safe-updates"),
1427
1569
   (char**) &select_limit,
1428
 
   (char**) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ULONG_MAX,
 
1570
   (char**) &select_limit, 0, GET_UINT32, REQUIRED_ARG, 1000L, 1, ULONG_MAX,
1429
1571
   0, 1, 0},
1430
1572
  {"max_join_size", OPT_MAX_JOIN_SIZE,
1431
1573
   N_("Automatic limit for rows in a join when using --safe-updates"),
1432
1574
   (char**) &max_join_size,
1433
 
   (char**) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ULONG_MAX,
 
1575
   (char**) &max_join_size, 0, GET_UINT32, REQUIRED_ARG, 1000000L, 1, ULONG_MAX,
1434
1576
   0, 1, 0},
1435
1577
  {"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
1578
   (char**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1437
1579
  {"show-warnings", OPT_SHOW_WARNINGS, N_("Show warnings after every statement."),
1438
1580
   (char**) &show_warnings, (char**) &show_warnings, 0, GET_BOOL, NO_ARG,
1439
1581
   0, 0, 0, 0, 0, 0},
 
1582
  {"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of lines before each import progress report."),
 
1583
   (char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
 
1584
   0, 0, 0, 0, 0, 0},
 
1585
  {"ping", OPT_PING, N_("Ping the server to check if it's alive."),
 
1586
   (char**) &opt_ping, (char**) &opt_ping, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1440
1587
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1441
1588
};
1442
1589
 
1445
1592
{
1446
1593
  const char* readline= "readline";
1447
1594
 
1448
 
  printf(_("%s  Ver %s Distrib %s, for %s (%s) using %s %s\n"),
1449
 
         my_progname, VER, drizzle_get_client_info(),
1450
 
         SYSTEM_TYPE, MACHINE_TYPE,
 
1595
  printf(_("%s  Ver %s Distrib %s, for %s-%s (%s) using %s %s\n"),
 
1596
         my_progname, VER.c_str(), drizzle_version(),
 
1597
         HOST_VENDOR, HOST_OS, HOST_CPU,
1451
1598
         readline, rl_library_version);
1452
1599
 
1453
1600
  if (version)
1454
1601
    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"));
 
1602
  printf(_("Copyright (C) 2008 Sun Microsystems\n"
 
1603
           "This software comes with ABSOLUTELY NO WARRANTY. "
 
1604
           "This is free software,\n"
 
1605
           "and you are welcome to modify and redistribute it "
 
1606
           "under the GPL license\n"));
1459
1607
  printf(_("Usage: %s [OPTIONS] [database]\n"), my_progname);
1460
1608
  my_print_help(my_long_options);
1461
 
  print_defaults("my", load_default_groups);
 
1609
  print_defaults("drizzle", load_default_groups);
1462
1610
  my_print_variables(my_long_options);
1463
1611
}
1464
1612
 
1465
1613
 
1466
 
bool
1467
 
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1468
 
               char *argument)
 
1614
extern "C" bool
 
1615
get_one_option(int optid, const struct my_option *, char *argument)
1469
1616
{
 
1617
  char *endchar= NULL;
 
1618
  uint64_t temp_drizzle_port= 0;
 
1619
 
1470
1620
  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
1621
  case  OPT_DEFAULT_CHARSET:
1476
1622
    default_charset_used= 1;
1477
1623
    break;
1478
1624
  case OPT_DELIMITER:
1479
1625
    if (argument == disabled_my_option)
1480
1626
    {
1481
 
      my_stpcpy(delimiter, DEFAULT_DELIMITER);
 
1627
      strcpy(delimiter, DEFAULT_DELIMITER);
1482
1628
    }
1483
1629
    else
1484
1630
    {
1485
1631
      /* Check that delimiter does not contain a backslash */
1486
1632
      if (!strstr(argument, "\\"))
1487
1633
      {
1488
 
        strmake(delimiter, argument, sizeof(delimiter) - 1);
 
1634
        strncpy(delimiter, argument, sizeof(delimiter) - 1);
1489
1635
      }
1490
1636
      else
1491
1637
      {
1492
1638
        put_info(_("DELIMITER cannot contain a backslash character"),
1493
1639
                 INFO_ERROR,0,0);
1494
 
        return 0;
 
1640
        return false;
1495
1641
      }
1496
1642
    }
1497
 
    delimiter_length= (uint)strlen(delimiter);
 
1643
    delimiter_length= (uint32_t)strlen(delimiter);
1498
1644
    delimiter_str= delimiter;
1499
1645
    break;
1500
 
  case OPT_LOCAL_INFILE:
1501
 
    using_opt_local_infile=1;
1502
 
    break;
1503
1646
  case OPT_TEE:
1504
1647
    if (argument == disabled_my_option)
1505
1648
    {
1523
1666
      if (argument && strlen(argument))
1524
1667
      {
1525
1668
        default_pager_set= 1;
1526
 
        strmake(pager, argument, sizeof(pager) - 1);
1527
 
        my_stpcpy(default_pager, pager);
 
1669
        strncpy(pager, argument, sizeof(pager) - 1);
 
1670
        strcpy(default_pager, pager);
1528
1671
      }
1529
1672
      else if (default_pager_set)
1530
 
        my_stpcpy(pager, default_pager);
 
1673
        strcpy(pager, default_pager);
1531
1674
      else
1532
1675
        opt_nopager= 1;
1533
1676
    }
1548
1691
  case 'e':
1549
1692
    status.batch= 1;
1550
1693
    status.add_to_history= 0;
1551
 
    if (!status.line_buff)
1552
 
      ignore_errors= 0;                         // do it for the first -e only
1553
 
    if (!(status.line_buff= batch_readline_command(status.line_buff, argument)))
1554
 
      return 1;
 
1694
    if (status.line_buff == NULL)
 
1695
      status.line_buff= new(std::nothrow) LineBuffer(opt_max_input_line,NULL);
 
1696
    if (status.line_buff == NULL)
 
1697
    {
 
1698
      my_end(0);
 
1699
      exit(1);
 
1700
    }
 
1701
    status.line_buff->addString(argument);
1555
1702
    break;
1556
1703
  case 'o':
1557
1704
    if (argument == disabled_my_option)
1560
1707
      one_database= skip_updates= 1;
1561
1708
    break;
1562
1709
  case 'p':
 
1710
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
 
1711
    /* if there is an alpha character this is not a valid port */
 
1712
    if (strlen(endchar) != 0)
 
1713
    {
 
1714
      put_info(_("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead."), INFO_ERROR, 0, 0);
 
1715
      return false;
 
1716
    }
 
1717
    /* If the port number is > 65535 it is not a valid port
 
1718
       This also helps with potential data loss casting unsigned long to a
 
1719
       uint32_t. */
 
1720
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
1721
    {
 
1722
      put_info(_("Value supplied for port is not valid."), INFO_ERROR, 0, 0);
 
1723
      return false;
 
1724
    }
 
1725
    else
 
1726
    {
 
1727
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
 
1728
    }
 
1729
    break;
 
1730
  case 'P':
 
1731
    /* Don't require password */
1563
1732
    if (argument == disabled_my_option)
1564
 
      argument= (char*) "";      // Don't require password
 
1733
    {
 
1734
      argument= (char*) "";
 
1735
    }
1565
1736
    if (argument)
1566
1737
    {
1567
1738
      char *start= argument;
1568
1739
      free(opt_password);
1569
1740
      opt_password= strdup(argument);
1570
 
      while (*argument) *argument++= 'x';        // Destroy argument
 
1741
      while (*argument)
 
1742
      {
 
1743
        /* Overwriting password with 'x' */
 
1744
        *argument++= 'x';
 
1745
      }
1571
1746
      if (*start)
1572
 
        start[1]=0 ;
 
1747
      {
 
1748
        start[1]= 0;
 
1749
      }
1573
1750
      tty_password= 0;
1574
1751
    }
1575
1752
    else
 
1753
    {
1576
1754
      tty_password= 1;
 
1755
    }
1577
1756
    break;
1578
1757
  case 's':
1579
1758
    if (argument == disabled_my_option)
1592
1771
    status.add_to_history= 0;
1593
1772
    set_if_bigger(opt_silent,1);                         // more silent
1594
1773
    break;
1595
 
    break;
1596
1774
  case 'V':
1597
1775
    usage(1);
1598
1776
    exit(0);
1609
1787
{
1610
1788
  char *tmp, *pagpoint;
1611
1789
  int ho_error;
1612
 
  const DRIZZLE_PARAMETERS *drizzle_params= drizzle_get_parameters();
1613
1790
 
1614
1791
  tmp= (char *) getenv("DRIZZLE_HOST");
1615
1792
  if (tmp)
1618
1795
  pagpoint= getenv("PAGER");
1619
1796
  if (!((char*) (pagpoint)))
1620
1797
  {
1621
 
    my_stpcpy(pager, "stdout");
 
1798
    strcpy(pager, "stdout");
1622
1799
    opt_nopager= 1;
1623
1800
  }
1624
1801
  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;
 
1802
    strcpy(pager, pagpoint);
 
1803
  strcpy(default_pager, pager);
1630
1804
 
1631
1805
  if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
1632
1806
    exit(ho_error);
1633
1807
 
1634
 
  *drizzle_params->p_max_allowed_packet= opt_max_allowed_packet;
1635
 
  *drizzle_params->p_net_buffer_length= opt_net_buffer_length;
1636
 
 
1637
1808
  if (status.batch) /* disable pager and outfile in this case */
1638
1809
  {
1639
 
    my_stpcpy(default_pager, "stdout");
1640
 
    my_stpcpy(pager, "stdout");
 
1810
    strcpy(default_pager, "stdout");
 
1811
    strcpy(pager, "stdout");
1641
1812
    opt_nopager= 1;
1642
1813
    default_pager_set= 0;
1643
1814
    opt_outfile= 0;
1644
1815
    opt_reconnect= 0;
1645
 
    connect_flag= 0; /* Not in interactive mode */
 
1816
    connect_flag= DRIZZLE_CAPABILITIES_NONE; /* Not in interactive mode */
1646
1817
  }
1647
1818
 
1648
1819
  if (argc > 1)
1657
1828
    current_db= strdup(*argv);
1658
1829
  }
1659
1830
  if (tty_password)
1660
 
    opt_password= get_tty_password(NULL);
 
1831
    opt_password= client_get_tty_password(NULL);
1661
1832
  if (debug_info_flag)
1662
1833
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1663
1834
  if (debug_check_flag)
1678
1849
  {
1679
1850
    if (!interactive)
1680
1851
    {
1681
 
      line=batch_readline(status.line_buff);
1682
 
      /*
1683
 
        Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF.
1684
 
        Editors like "notepad" put this marker in
1685
 
        the very beginning of a text file when
1686
 
        you save the file using "Unicode UTF-8" format.
1687
 
      */
1688
 
      if (!line_number &&
1689
 
          (unsigned char) line[0] == 0xEF &&
1690
 
          (unsigned char) line[1] == 0xBB &&
1691
 
          (unsigned char) line[2] == 0xBF)
1692
 
        line+= 3;
 
1852
      if (status.line_buff)
 
1853
        line= status.line_buff->readline();
 
1854
      else
 
1855
        line= 0;
 
1856
 
1693
1857
      line_number++;
 
1858
      if (show_progress_size > 0)
 
1859
      {
 
1860
        if ((line_number % show_progress_size) == 0)
 
1861
          fprintf(stderr, _("Processing line: %"PRIu32"\n"), line_number);
 
1862
      }
1694
1863
      if (!glob_buffer->empty())
1695
 
        status.query_start_line=line_number;
 
1864
        status.query_start_line= line_number;
1696
1865
    }
1697
1866
    else
1698
1867
    {
1762
1931
 
1763
1932
static COMMANDS *find_command(const char *name,char cmd_char)
1764
1933
{
1765
 
  uint len;
 
1934
  uint32_t len;
1766
1935
  const char *end;
1767
1936
 
1768
1937
  if (!name)
1788
1957
      return((COMMANDS *) 0);
1789
1958
    if ((end=strcont(name," \t")))
1790
1959
    {
1791
 
      len=(uint) (end - name);
 
1960
      len=(uint32_t) (end - name);
1792
1961
      while (my_isspace(charset_info,*end))
1793
1962
        end++;
1794
1963
      if (!*end)
1795
1964
        end=0;          // no arguments to function
1796
1965
    }
1797
1966
    else
1798
 
      len=(uint) strlen(name);
 
1967
      len=(uint32_t) strlen(name);
1799
1968
  }
1800
1969
 
1801
 
  for (uint i= 0; commands[i].name; i++)
 
1970
  for (uint32_t i= 0; commands[i].name; i++)
1802
1971
  {
1803
1972
    if (commands[i].func &&
1804
1973
        ((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)))
1814
1983
                        bool *ml_comment)
1815
1984
{
1816
1985
  unsigned char inchar;
1817
 
  char buff[80], *pos, *out;
 
1986
  char *pos, *out;
1818
1987
  COMMANDS *com;
1819
1988
  bool need_space= 0;
1820
1989
  bool ss_comment= 0;
1824
1993
    return(0);
1825
1994
  if (status.add_to_history && line[0] && not_in_history(line))
1826
1995
    add_history(line);
1827
 
  char *end_of_line=line+(uint) strlen(line);
 
1996
  char *end_of_line=line+(uint32_t) strlen(line);
1828
1997
 
1829
1998
  for (pos=out=line ; (inchar= (unsigned char) *pos) ; pos++)
1830
1999
  {
1836
2005
        continue;
1837
2006
    }
1838
2007
 
1839
 
#ifdef USE_MB
1840
2008
    // Accept multi-byte characters as-is
1841
2009
    int length;
1842
2010
    if (use_mb(charset_info) &&
1852
2020
        pos+= length - 1;
1853
2021
      continue;
1854
2022
    }
1855
 
#endif
1856
 
        if (!*ml_comment && inchar == '\\' &&
1857
 
            !(*in_string && (drizzle.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)))
 
2023
    if (!*ml_comment && inchar == '\\' &&
 
2024
        !(*in_string && (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_NO_BACKSLASH_ESCAPES)))
1858
2025
    {
1859
2026
      // Found possbile one character command like \c
1860
2027
 
1894
2061
          {
1895
2062
            for (pos++ ;
1896
2063
                 *pos && (*pos != *delimiter ||
1897
 
                          !is_prefix(pos + 1, delimiter + 1)) ; pos++)
 
2064
                          strncmp(pos + 1, delimiter + 1,
 
2065
                                  strlen(delimiter + 1))) ; pos++)
1898
2066
              ;  // Remove parameters
1899
2067
            if (!*pos)
1900
2068
              pos--;
1905
2073
      }
1906
2074
      else
1907
2075
      {
1908
 
        sprintf(buff,_("Unknown command '\\%c'."),inchar);
1909
 
        if (put_info(buff,INFO_ERROR,0,0) > 0)
 
2076
        string buff(_("Unknown command: "));
 
2077
        buff.push_back('\'');
 
2078
        buff.push_back(inchar);
 
2079
        buff.push_back('\'');
 
2080
        buff.push_back('.');
 
2081
        if (put_info(buff.c_str(),INFO_ERROR,0,0) > 0)
1910
2082
          return(1);
1911
2083
        *out++='\\';
1912
2084
        *out++=(char) inchar;
1945
2117
      buffer->clear();
1946
2118
      break;
1947
2119
    }
1948
 
    else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter))
 
2120
    else if (!*ml_comment && !*in_string && !strncmp(pos, delimiter,
 
2121
                                                     strlen(delimiter)))
1949
2122
    {
1950
2123
      // Found a statement. Continue parsing after the delimiter
1951
2124
      pos+= delimiter_length;
2068
2241
  if (out != line || (buffer->length() > 0))
2069
2242
  {
2070
2243
    *out++='\n';
2071
 
    uint length=(uint) (out-line);
 
2244
    uint32_t length=(uint32_t) (out-line);
2072
2245
    if ((!*ml_comment || preserve_comments))
2073
2246
      buffer->append(line, length);
2074
2247
  }
2081
2254
 
2082
2255
 
2083
2256
static char **mysql_completion (const char *text, int start, int end);
2084
 
static char *new_command_generator(const char *text, int);
 
2257
extern "C" char *new_command_generator(const char *text, int);
2085
2258
 
2086
2259
/*
2087
2260
  Tell the GNU Readline library how to complete.  We want to try to complete
2088
2261
  on command names if this is the first word in the line, or on filenames
2089
2262
  if not.
2090
2263
*/
2091
 
static char *no_completion(const char * a __attribute__((unused)),
2092
 
                           int b __attribute__((unused)))
 
2264
static char *no_completion(const char *, int)
2093
2265
{
2094
2266
  /* No filename completion */
2095
2267
  return 0;
2184
2356
  entire line in case we want to do some simple parsing.  Return the
2185
2357
  array of matches, or NULL if there aren't any.
2186
2358
*/
2187
 
char **mysql_completion (const char *text,
2188
 
                        int start __attribute__((unused)),
2189
 
                        int end __attribute__((unused)))
 
2359
char **mysql_completion (const char *text, int, int)
2190
2360
{
2191
2361
  if (!status.batch && !quick)
2192
2362
    return rl_completion_matches(text, new_command_generator);
2194
2364
    return (char**) 0;
2195
2365
}
2196
2366
 
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;
 
2367
inline string lower_string(const string &from_string)
 
2368
{
 
2369
  string to_string= from_string;
 
2370
  transform(to_string.begin(), to_string.end(),
 
2371
            to_string.begin(), ::tolower);
 
2372
  return to_string;
 
2373
}
 
2374
inline string lower_string(const char * from_string)
 
2375
{
 
2376
  string to_string= from_string;
 
2377
  return lower_string(to_string);
 
2378
}
 
2379
 
 
2380
template <class T>
 
2381
class CompletionMatch :
 
2382
  public unary_function<const string&, bool>
 
2383
{
 
2384
  string match_text; 
 
2385
  T match_func;
 
2386
public:
 
2387
  CompletionMatch(string text) : match_text(text) {}
 
2388
  inline bool operator() (const pair<string,string> &match_against) const
 
2389
  {
 
2390
    string sub_match=
 
2391
      lower_string(match_against.first.substr(0,match_text.size()));
 
2392
    return match_func(sub_match,match_text);
 
2393
  }
 
2394
};
 
2395
 
 
2396
 
 
2397
 
 
2398
extern "C"
 
2399
char *new_command_generator(const char *text, int state)
 
2400
{
2205
2401
 
2206
2402
  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;
 
2403
  {
 
2404
    completion_string= lower_string(text);
 
2405
    if (completion_string.size() == 0)
 
2406
    {
 
2407
      completion_iter= completion_map.begin();
 
2408
      completion_end= completion_map.end();
 
2409
    }
 
2410
    else
 
2411
    {
 
2412
      completion_iter= find_if(completion_map.begin(), completion_map.end(),
 
2413
                               CompletionMatch<equal_to<string> >(completion_string));
 
2414
      completion_end= find_if(completion_iter, completion_map.end(),
 
2415
                              CompletionMatch<not_equal_to<string> >(completion_string));
 
2416
    }
 
2417
  }
 
2418
  if (completion_iter == completion_end || (size_t)state > completion_map.size())
 
2419
    return NULL;
 
2420
  char *result= (char *)malloc((*completion_iter).second.size()+1);
 
2421
  strcpy(result, (*completion_iter).second.c_str());
 
2422
  completion_iter++;
 
2423
  return result;
2274
2424
}
2275
2425
 
2276
 
 
2277
2426
/* Build up the completion hash */
2278
2427
 
2279
2428
static void build_completion_hash(bool rehash, bool write_info)
2280
2429
{
2281
2430
  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
 
 
 
2431
  drizzle_return_t ret;
 
2432
  drizzle_result_st databases,tables,fields;
 
2433
  drizzle_row_t database_row,table_row;
 
2434
  drizzle_column_st *sql_field;
 
2435
  string tmp_str, tmp_str_lower;
2290
2436
 
2291
2437
  if (status.batch || quick || !current_db)
2292
2438
    return;      // We don't need completion in batches
2293
2439
  if (!rehash)
2294
2440
    return;
2295
2441
 
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));
 
2442
  completion_map.clear();
2301
2443
 
2302
2444
  /* hash this file's known subset of SQL commands */
2303
2445
  while (cmd->name) {
2304
 
    add_word(&ht,(char*) cmd->name);
 
2446
    tmp_str= cmd->name;
 
2447
    tmp_str_lower= lower_string(tmp_str);
 
2448
    completion_map[tmp_str_lower]= tmp_str;
2305
2449
    cmd++;
2306
2450
  }
2307
2451
 
2308
2452
  /* hash Drizzle functions (to be implemented) */
2309
2453
 
2310
2454
  /* hash all database names */
2311
 
  if (drizzle_query(&drizzle,"show databases") == 0)
 
2455
  if (drizzle_query_str(&con, &databases, "show databases", &ret) != NULL)
2312
2456
  {
2313
 
    if (!(databases = drizzle_store_result(&drizzle)))
2314
 
      put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
2315
 
    else
 
2457
    if (ret == DRIZZLE_RETURN_OK)
2316
2458
    {
2317
 
      while ((database_row=drizzle_fetch_row(databases)))
 
2459
      if (drizzle_result_buffer(&databases) != DRIZZLE_RETURN_OK)
 
2460
        put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
 
2461
      else
2318
2462
      {
2319
 
        char *str=strdup_root(&hash_mem_root, (char*) database_row[0]);
2320
 
        if (str)
2321
 
          add_word(&ht,(char*) str);
 
2463
        while ((database_row=drizzle_row_next(&databases)))
 
2464
        {
 
2465
          tmp_str= database_row[0];
 
2466
          tmp_str_lower= lower_string(tmp_str);
 
2467
          completion_map[tmp_str_lower]= tmp_str;
 
2468
        }
2322
2469
      }
2323
 
      drizzle_free_result(databases);
2324
2470
    }
 
2471
 
 
2472
    drizzle_result_free(&databases);
2325
2473
  }
 
2474
 
2326
2475
  /* hash all table names */
2327
 
  if (drizzle_query(&drizzle,"show tables")==0)
 
2476
  if (drizzle_query_str(&con, &tables, "show tables", &ret) != NULL)
2328
2477
  {
2329
 
    if (!(tables = drizzle_store_result(&drizzle)))
 
2478
    if (ret != DRIZZLE_RETURN_OK)
 
2479
    {
 
2480
      drizzle_result_free(&tables);
 
2481
      return;
 
2482
    }
 
2483
 
 
2484
    if (drizzle_result_buffer(&tables) != DRIZZLE_RETURN_OK)
2330
2485
      put_info(drizzle_error(&drizzle),INFO_INFO,0,0);
2331
2486
    else
2332
2487
    {
2333
 
      if (drizzle_num_rows(tables) > 0 && !opt_silent && write_info)
 
2488
      if (drizzle_result_row_count(&tables) > 0 && !opt_silent && write_info)
2334
2489
      {
2335
2490
        tee_fprintf(stdout, _("\
2336
2491
Reading table information for completion of table and column names\n    \
2337
2492
You can turn off this feature to get a quicker startup with -A\n\n"));
2338
2493
      }
2339
 
      while ((table_row=drizzle_fetch_row(tables)))
 
2494
      while ((table_row=drizzle_row_next(&tables)))
2340
2495
      {
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);
 
2496
        tmp_str= table_row[0];
 
2497
        tmp_str_lower= lower_string(tmp_str);
 
2498
        completion_map[tmp_str_lower]= tmp_str;
2345
2499
      }
2346
2500
    }
2347
2501
  }
 
2502
  else
 
2503
    return;
2348
2504
 
2349
2505
  /* 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)))
 
2506
  if (drizzle_result_row_count(&tables) == 0)
 
2507
  {
 
2508
    drizzle_result_free(&tables);
 
2509
    return;
 
2510
  }
 
2511
 
 
2512
  drizzle_row_seek(&tables, 0);
 
2513
 
 
2514
  while ((table_row=drizzle_row_next(&tables)))
 
2515
  {
 
2516
    string query;
 
2517
 
 
2518
    query.append("show fields in '");
 
2519
    query.append(table_row[0]);
 
2520
    query.append("'");
 
2521
    
 
2522
    if (drizzle_query(&con, &fields, query.c_str(), query.length(),
 
2523
                      &ret) != NULL)
2365
2524
    {
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);
 
2525
      if (ret == DRIZZLE_RETURN_OK &&
 
2526
          drizzle_result_buffer(&fields) == DRIZZLE_RETURN_OK)
 
2527
      {
 
2528
        while ((sql_field=drizzle_column_next(&fields)))
 
2529
        {
 
2530
          tmp_str=table_row[0];
 
2531
          tmp_str.append(".");
 
2532
          tmp_str.append(drizzle_column_name(sql_field));
 
2533
          tmp_str_lower= lower_string(tmp_str);
 
2534
          completion_map[tmp_str_lower]= tmp_str;
 
2535
 
 
2536
          tmp_str=drizzle_column_name(sql_field);
 
2537
          tmp_str_lower= lower_string(tmp_str);
 
2538
          completion_map[tmp_str_lower]= tmp_str;
 
2539
        }
 
2540
      }
 
2541
      drizzle_result_free(&fields);
2389
2542
    }
2390
 
    else
2391
 
      field_names[i]= 0;
2392
 
 
2393
 
    i++;
2394
2543
  }
2395
 
  drizzle_free_result(tables);
2396
 
  field_names[i]=0;        // End pointer
2397
 
  return;
 
2544
  drizzle_result_free(&tables);
 
2545
  completion_iter= completion_map.begin();
2398
2546
}
2399
2547
 
2400
2548
/* for gnu readline */
2426
2574
 
2427
2575
static int reconnect(void)
2428
2576
{
2429
 
  /* purecov: begin tested */
2430
2577
  if (opt_reconnect)
2431
2578
  {
2432
2579
    put_info(_("No connection. Trying to reconnect..."),INFO_INFO,0,0);
2433
2580
    (void) com_connect((string *)0, 0);
2434
 
    if (opt_rehash)
 
2581
    if (opt_rehash && connected)
2435
2582
      com_rehash(NULL, NULL);
2436
2583
  }
2437
 
  if (!connected)
 
2584
  if (! connected)
2438
2585
    return put_info(_("Can't connect to the server\n"),INFO_ERROR,0,0);
2439
 
  /* purecov: end */
2440
2586
  return 0;
2441
2587
}
2442
2588
 
2443
2589
static void get_current_db(void)
2444
2590
{
2445
 
  DRIZZLE_RES *res;
 
2591
  drizzle_return_t ret;
 
2592
  drizzle_result_st res;
2446
2593
 
2447
2594
  free(current_db);
2448
2595
  current_db= NULL;
2449
2596
  /* In case of error below current_db will be NULL */
2450
 
  if (!drizzle_query(&drizzle, "SELECT DATABASE()") &&
2451
 
      (res= drizzle_use_result(&drizzle)))
 
2597
  if (drizzle_query_str(&con, &res, "SELECT DATABASE()", &ret) != NULL)
2452
2598
  {
2453
 
    DRIZZLE_ROW row= drizzle_fetch_row(res);
2454
 
    if (row[0])
2455
 
      current_db= strdup(row[0]);
2456
 
    drizzle_free_result(res);
 
2599
    if (ret == DRIZZLE_RETURN_OK &&
 
2600
        drizzle_result_buffer(&res) == DRIZZLE_RETURN_OK)
 
2601
    {
 
2602
      drizzle_row_t row= drizzle_row_next(&res);
 
2603
      if (row[0])
 
2604
        current_db= strdup(row[0]);
 
2605
      drizzle_result_free(&res);
 
2606
    }
2457
2607
  }
2458
2608
}
2459
2609
 
2461
2611
 The different commands
2462
2612
***************************************************************************/
2463
2613
 
2464
 
int drizzle_real_query_for_lazy(const char *buf, int length)
 
2614
int drizzleclient_real_query_for_lazy(const char *buf, int length,
 
2615
                                      drizzle_result_st *result,
 
2616
                                      uint32_t *error_code)
2465
2617
{
2466
 
  for (uint retry=0;; retry++)
 
2618
  drizzle_return_t ret;
 
2619
 
 
2620
  for (uint32_t retry=0;; retry++)
2467
2621
  {
2468
2622
    int error;
2469
 
    if (!drizzle_real_query(&drizzle,buf,length))
 
2623
    if (drizzle_query(&con,result,buf,length,&ret) != NULL &&
 
2624
        ret == DRIZZLE_RETURN_OK)
 
2625
    {
2470
2626
      return 0;
2471
 
    error= put_error(&drizzle);
2472
 
    if (drizzle_errno(&drizzle) != CR_SERVER_GONE_ERROR || retry > 1 ||
 
2627
    }
 
2628
    error= put_error(&con, result);
 
2629
 
 
2630
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2631
    {
 
2632
      *error_code= drizzle_result_error_code(result);
 
2633
      drizzle_result_free(result);
 
2634
    }
 
2635
 
 
2636
    if (ret != DRIZZLE_RETURN_SERVER_GONE || retry > 1 ||
2473
2637
        !opt_reconnect)
 
2638
    {
2474
2639
      return error;
 
2640
    }
 
2641
 
2475
2642
    if (reconnect())
2476
2643
      return error;
2477
2644
  }
2478
2645
}
2479
2646
 
2480
 
int drizzle_store_result_for_lazy(DRIZZLE_RES **result)
 
2647
int drizzleclient_store_result_for_lazy(drizzle_result_st *result)
2481
2648
{
2482
 
  if ((*result=drizzle_store_result(&drizzle)))
 
2649
  if (drizzle_result_buffer(result) == DRIZZLE_RETURN_OK)
2483
2650
    return 0;
2484
2651
 
2485
 
  if (drizzle_error(&drizzle)[0])
2486
 
    return put_error(&drizzle);
 
2652
  if (drizzle_con_error(&con)[0])
 
2653
    return put_error(&con, result);
2487
2654
  return 0;
2488
2655
}
2489
2656
 
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
2657
static int
2594
 
com_help(string *buffer __attribute__((unused)),
2595
 
         const char *line __attribute__((unused)))
 
2658
com_help(string *buffer, const char *)
2596
2659
{
2597
2660
  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
 
  }
 
2661
  char buff[32], *end;
2605
2662
 
2606
2663
  put_info(_("List of all Drizzle commands:"), INFO_INFO,0,0);
2607
2664
  if (!named_cmds)
2608
2665
    put_info(_("Note that all text commands must be first on line and end with ';'"),INFO_INFO,0,0);
2609
2666
  for (i = 0; commands[i].name; i++)
2610
2667
  {
2611
 
    end= my_stpcpy(buff, commands[i].name);
 
2668
    end= strcpy(buff, commands[i].name);
 
2669
    end+= strlen(commands[i].name);
2612
2670
    for (j= (int)strlen(commands[i].name); j < 10; j++)
2613
 
      end= my_stpcpy(end, " ");
 
2671
      end= strcpy(end, " ")+1;
2614
2672
    if (commands[i].func)
2615
2673
      tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
2616
2674
                  commands[i].cmd_char, _(commands[i].doc));
2617
2675
  }
2618
 
  if (connected && drizzle_get_server_version(&drizzle) >= 40100)
2619
 
    put_info(_("\nFor server side help, type 'help contents'\n"), INFO_INFO,0,0);
 
2676
  tee_fprintf(stdout, "\n");
 
2677
  buffer->clear();
2620
2678
  return 0;
2621
2679
}
2622
2680
 
2623
2681
 
2624
2682
static int
2625
 
com_clear(string *buffer,
2626
 
          const char *line __attribute__((unused)))
 
2683
com_clear(string *buffer, const char *)
2627
2684
{
2628
2685
  if (status.add_to_history)
2629
2686
    fix_history(buffer);
2639
2696
  1  if fatal error
2640
2697
*/
2641
2698
static int
2642
 
com_go(string *buffer,
2643
 
       const char *line __attribute__((unused)))
 
2699
com_go(string *buffer, const char *)
2644
2700
{
2645
2701
  char          buff[200]; /* about 110 chars used so far */
2646
2702
  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;
 
2703
  drizzle_result_st result;
 
2704
  drizzle_return_t ret;
 
2705
  uint32_t      timer, warnings= 0;
 
2706
  uint32_t      error= 0;
 
2707
  uint32_t      error_code= 0;
2650
2708
  int           err= 0;
2651
2709
 
2652
2710
  interrupted_query= 0;
2680
2738
 
2681
2739
  timer=start_timer();
2682
2740
  executing_query= 1;
2683
 
  error= drizzle_real_query_for_lazy(buffer->c_str(),buffer->length());
 
2741
  error= drizzleclient_real_query_for_lazy(buffer->c_str(),buffer->length(),&result, &error_code);
2684
2742
 
2685
2743
  if (status.add_to_history)
2686
2744
  {
2700
2758
 
2701
2759
    if (quick)
2702
2760
    {
2703
 
      if (!(result=drizzle_use_result(&drizzle)) && drizzle_field_count(&drizzle))
 
2761
      if (drizzle_column_buffer(&result) != DRIZZLE_RETURN_OK)
2704
2762
      {
2705
 
        error= put_error(&drizzle);
 
2763
        error= put_error(&con, &result);
2706
2764
        goto end;
2707
2765
      }
2708
2766
    }
2709
2767
    else
2710
2768
    {
2711
 
      error= drizzle_store_result_for_lazy(&result);
 
2769
      error= drizzleclient_store_result_for_lazy(&result);
2712
2770
      if (error)
2713
2771
        goto end;
2714
2772
    }
2719
2777
      time_buff[0]= '\0';
2720
2778
 
2721
2779
    /* Every branch must truncate  buff . */
2722
 
    if (result)
 
2780
    if (drizzle_result_column_count(&result) > 0)
2723
2781
    {
2724
 
      if (!drizzle_num_rows(result) && ! quick && !column_types_flag)
 
2782
      if (!quick && drizzle_result_row_count(&result) == 0 &&
 
2783
          !column_types_flag)
2725
2784
      {
2726
 
        my_stpcpy(buff, _("Empty set"));
 
2785
        strcpy(buff, _("Empty set"));
2727
2786
      }
2728
2787
      else
2729
2788
      {
2730
2789
        init_pager();
2731
2790
        if (vertical || (auto_vertical_output &&
2732
 
                         (terminal_width < get_result_width(result))))
2733
 
          print_table_data_vertically(result);
 
2791
                         (terminal_width < get_result_width(&result))))
 
2792
          print_table_data_vertically(&result);
2734
2793
        else if (opt_silent && verbose <= 2 && !output_tables)
2735
 
          print_tab_data(result);
 
2794
          print_tab_data(&result);
2736
2795
        else
2737
 
          print_table_data(result);
 
2796
          print_table_data(&result);
2738
2797
        sprintf(buff,
2739
2798
                ngettext("%ld row in set","%ld rows in set",
2740
 
                         (long) drizzle_num_rows(result)),
2741
 
                (long) drizzle_num_rows(result));
 
2799
                         (long) drizzle_result_row_count(&result)),
 
2800
                (long) drizzle_result_row_count(&result));
2742
2801
        end_pager();
2743
 
        if (drizzle_errno(&drizzle))
2744
 
          error= put_error(&drizzle);
 
2802
        if (drizzle_result_error_code(&result))
 
2803
          error= put_error(&con, &result);
2745
2804
      }
2746
2805
    }
2747
 
    else if (drizzle_affected_rows(&drizzle) == ~(uint64_t) 0)
2748
 
      my_stpcpy(buff,_("Query OK"));
 
2806
    else if (drizzle_result_affected_rows(&result) == ~(uint64_t) 0)
 
2807
      strcpy(buff,_("Query OK"));
2749
2808
    else
2750
2809
      sprintf(buff, ngettext("Query OK, %ld row affected",
2751
2810
                             "Query OK, %ld rows affected",
2752
 
                             (long) drizzle_affected_rows(&drizzle)),
2753
 
              (long) drizzle_affected_rows(&drizzle));
 
2811
                             (long) drizzle_result_affected_rows(&result)),
 
2812
              (long) drizzle_result_affected_rows(&result));
2754
2813
 
2755
2814
    pos= strchr(buff, '\0');
2756
 
    if ((warnings= drizzle_warning_count(&drizzle)))
 
2815
    if ((warnings= drizzle_result_warning_count(&result)))
2757
2816
    {
2758
2817
      *pos++= ',';
2759
2818
      *pos++= ' ';
2760
 
      pos=int10_to_str(warnings, pos, 10);
2761
 
      pos=my_stpcpy(pos, " warning");
 
2819
      char warnings_buff[20];
 
2820
      memset(warnings_buff,0,20);
 
2821
      sprintf(warnings_buff, "%d", warnings);
 
2822
      strcpy(pos, warnings_buff);
 
2823
      pos+= strlen(warnings_buff);
 
2824
      pos= strcpy(pos, " warning")+8;
2762
2825
      if (warnings != 1)
2763
2826
        *pos++= 's';
2764
2827
    }
2765
 
    my_stpcpy(pos, time_buff);
 
2828
    strcpy(pos, time_buff);
2766
2829
    put_info(buff,INFO_RESULT,0,0);
2767
 
    if (drizzle_info(&drizzle))
2768
 
      put_info(drizzle_info(&drizzle),INFO_RESULT,0,0);
 
2830
    if (strcmp(drizzle_result_info(&result), ""))
 
2831
      put_info(drizzle_result_info(&result),INFO_RESULT,0,0);
2769
2832
    put_info("",INFO_RESULT,0,0);      // Empty row
2770
2833
 
2771
 
    if (result && !drizzle_eof(result))  /* Something wrong when using quick */
2772
 
      error= put_error(&drizzle);
2773
 
    else if (unbuffered)
 
2834
    if (unbuffered)
2774
2835
      fflush(stdout);
2775
 
    drizzle_free_result(result);
2776
 
  } while (!(err= drizzle_next_result(&drizzle)));
 
2836
    drizzle_result_free(&result);
 
2837
 
 
2838
    if (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS)
 
2839
    {
 
2840
      if (drizzle_result_read(&con, &result, &ret) == NULL ||
 
2841
          ret != DRIZZLE_RETURN_OK)
 
2842
      {
 
2843
        if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
2844
        {
 
2845
          error_code= drizzle_result_error_code(&result);
 
2846
          drizzle_result_free(&result);
 
2847
        }
 
2848
 
 
2849
        error= put_error(&con, NULL);
 
2850
        goto end;
 
2851
      }
 
2852
    }
 
2853
 
 
2854
  } while (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_MORE_RESULTS_EXISTS);
2777
2855
  if (err >= 1)
2778
 
    error= put_error(&drizzle);
 
2856
    error= put_error(&con, NULL);
2779
2857
 
2780
2858
end:
2781
2859
 
2782
2860
  /* Show warnings if any or error occured */
2783
2861
  if (show_warnings == 1 && (warnings >= 1 || error))
2784
 
    print_warnings();
 
2862
    print_warnings(error_code);
2785
2863
 
2786
2864
  if (!error && !status.batch &&
2787
 
      (drizzle.server_status & SERVER_STATUS_DB_DROPPED))
 
2865
      drizzle_con_status(&con) & DRIZZLE_CON_STATUS_DB_DROPPED)
 
2866
  {
2788
2867
    get_current_db();
 
2868
  }
2789
2869
 
2790
2870
  executing_query= 0;
2791
2871
  return error;        /* New command follows */
2818
2898
  FILE* new_outfile;
2819
2899
  if (opt_outfile)
2820
2900
    end_tee();
2821
 
  if (!(new_outfile= my_fopen(file_name, O_APPEND | O_WRONLY, MYF(MY_WME))))
 
2901
  if (!(new_outfile= fopen(file_name, "a")))
2822
2902
  {
2823
2903
    tee_fprintf(stdout, "Error logging to file '%s'\n", file_name);
2824
2904
    return;
2825
2905
  }
2826
2906
  OUTFILE = new_outfile;
2827
 
  strmake(outfile, file_name, FN_REFLEN-1);
 
2907
  strncpy(outfile, file_name, FN_REFLEN-1);
2828
2908
  tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
2829
2909
  opt_outfile= 1;
 
2910
 
2830
2911
  return;
2831
2912
}
2832
2913
 
2833
2914
 
2834
2915
static void end_tee()
2835
2916
{
2836
 
  my_fclose(OUTFILE, MYF(0));
 
2917
  fclose(OUTFILE);
2837
2918
  OUTFILE= 0;
2838
2919
  opt_outfile= 0;
2839
2920
  return;
2852
2933
}
2853
2934
 
2854
2935
 
2855
 
static const char *fieldtype2str(enum enum_field_types type)
 
2936
static const char *fieldtype2str(drizzle_column_type_t type)
2856
2937
{
2857
2938
  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";
 
2939
    case DRIZZLE_COLUMN_TYPE_BLOB:        return "BLOB";
 
2940
    case DRIZZLE_COLUMN_TYPE_DATE:        return "DATE";
 
2941
    case DRIZZLE_COLUMN_TYPE_DATETIME:    return "DATETIME";
 
2942
    case DRIZZLE_COLUMN_TYPE_NEWDECIMAL:  return "DECIMAL";
 
2943
    case DRIZZLE_COLUMN_TYPE_DOUBLE:      return "DOUBLE";
 
2944
    case DRIZZLE_COLUMN_TYPE_ENUM:        return "ENUM";
 
2945
    case DRIZZLE_COLUMN_TYPE_LONG:        return "LONG";
 
2946
    case DRIZZLE_COLUMN_TYPE_LONGLONG:    return "LONGLONG";
 
2947
    case DRIZZLE_COLUMN_TYPE_NULL:        return "NULL";
 
2948
    case DRIZZLE_COLUMN_TYPE_TIMESTAMP:   return "TIMESTAMP";
 
2949
    case DRIZZLE_COLUMN_TYPE_TINY:        return "TINY";
 
2950
    case DRIZZLE_COLUMN_TYPE_VIRTUAL:     return "VIRTUAL";
2870
2951
    default:                     return "?-unknown-?";
2871
2952
  }
2872
2953
}
2873
2954
 
2874
 
static char *fieldflags2str(uint f) {
 
2955
static char *fieldflags2str(uint32_t f) {
2875
2956
  static char buf[1024];
2876
2957
  char *s=buf;
2877
2958
  *s=0;
2878
2959
#define ff2s_check_flag(X)                                              \
2879
 
  if (f & X ## _FLAG) { s=my_stpcpy(s, # X " "); f &= ~ X ## _FLAG; }
 
2960
  if (f & DRIZZLE_COLUMN_FLAGS_ ## X) { s=strcpy(s, # X " ")+strlen(# X " "); \
 
2961
                        f &= ~ DRIZZLE_COLUMN_FLAGS_ ## X; }
2880
2962
  ff2s_check_flag(NOT_NULL);
2881
2963
  ff2s_check_flag(PRI_KEY);
2882
2964
  ff2s_check_flag(UNIQUE_KEY);
2902
2984
}
2903
2985
 
2904
2986
static void
2905
 
print_field_types(DRIZZLE_RES *result)
 
2987
print_field_types(drizzle_result_st *result)
2906
2988
{
2907
 
  DRIZZLE_FIELD   *field;
2908
 
  uint i=0;
 
2989
  drizzle_column_st   *field;
 
2990
  uint32_t i=0;
2909
2991
 
2910
 
  while ((field = drizzle_fetch_field(result)))
 
2992
  while ((field = drizzle_column_next(result)))
2911
2993
  {
2912
2994
    tee_fprintf(PAGER, "Field %3u:  `%s`\n"
2913
2995
                "Catalog:    `%s`\n"
2921
3003
                "Decimals:   %u\n"
2922
3004
                "Flags:      %s\n\n",
2923
3005
                ++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));
 
3006
                drizzle_column_name(field), drizzle_column_catalog(field),
 
3007
                drizzle_column_db(field), drizzle_column_table(field),
 
3008
                drizzle_column_orig_table(field),
 
3009
                fieldtype2str(drizzle_column_type(field)),
 
3010
                get_charset_name(drizzle_column_charset(field)),
 
3011
                drizzle_column_charset(field), drizzle_column_size(field),
 
3012
                drizzle_column_max_size(field), drizzle_column_decimals(field),
 
3013
                fieldflags2str(drizzle_column_flags(field)));
2929
3014
  }
2930
3015
  tee_puts("", PAGER);
2931
3016
}
2932
3017
 
2933
3018
 
2934
3019
static void
2935
 
print_table_data(DRIZZLE_RES *result)
 
3020
print_table_data(drizzle_result_st *result)
2936
3021
{
2937
 
  DRIZZLE_ROW     cur;
2938
 
  DRIZZLE_FIELD   *field;
2939
 
  bool          *num_flag;
 
3022
  drizzle_row_t cur;
 
3023
  drizzle_return_t ret;
 
3024
  drizzle_column_st *field;
 
3025
  bool *num_flag;
2940
3026
  string separator;
2941
 
  
 
3027
 
2942
3028
  separator.reserve(256);
2943
3029
 
2944
 
  num_flag=(bool*) my_malloc(sizeof(bool)*drizzle_num_fields(result),
2945
 
                             MYF(MY_WME));
 
3030
  num_flag=(bool*) malloc(sizeof(bool)*drizzle_result_column_count(result));
2946
3031
  if (column_types_flag)
2947
3032
  {
2948
3033
    print_field_types(result);
2949
 
    if (!drizzle_num_rows(result))
 
3034
    if (!drizzle_result_row_count(result))
2950
3035
      return;
2951
 
    drizzle_field_seek(result,0);
 
3036
    drizzle_column_seek(result,0);
2952
3037
  }
2953
3038
  separator.append("+");
2954
 
  while ((field = drizzle_fetch_field(result)))
 
3039
  while ((field = drizzle_column_next(result)))
2955
3040
  {
2956
 
    uint32_t length= column_names ? field->name_length : 0;
 
3041
    uint32_t x, length= 0;
 
3042
 
 
3043
    if (column_names)
 
3044
    {
 
3045
      uint32_t name_length= strlen(drizzle_column_name(field));
 
3046
 
 
3047
      /* Check if the max_byte value is really the maximum in terms
 
3048
         of visual length since multibyte characters can affect the
 
3049
         length of the separator. */
 
3050
      length= charset_info->cset->numcells(charset_info,
 
3051
                                           drizzle_column_name(field),
 
3052
                                           drizzle_column_name(field) +
 
3053
                                           name_length);
 
3054
 
 
3055
      if (name_length == drizzle_column_max_size(field))
 
3056
      {
 
3057
        if (length < drizzle_column_max_size(field))
 
3058
          drizzle_column_set_max_size(field, length);
 
3059
      }
 
3060
      else
 
3061
      {
 
3062
        length= name_length;
 
3063
      }
 
3064
    }
 
3065
  
2957
3066
    if (quick)
2958
 
      length=max(length,field->length);
 
3067
      length=max(length,drizzle_column_size(field));
2959
3068
    else
2960
 
      length=max(length,field->max_length);
2961
 
    if (length < 4 && !(field->flags & NOT_NULL_FLAG))
 
3069
      length=max(length,(uint32_t)drizzle_column_max_size(field));
 
3070
    if (length < 4 &&
 
3071
        !(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
 
3072
    {
2962
3073
      // Room for "NULL"
2963
3074
      length=4;
2964
 
    field->max_length=length;
2965
 
    uint x;
 
3075
    }
 
3076
    drizzle_column_set_max_size(field, length);
 
3077
 
2966
3078
    for (x=0; x< (length+2); x++)
2967
3079
      separator.append("-");
2968
3080
    separator.append("+");
2971
3083
  tee_puts((char*) separator.c_str(), PAGER);
2972
3084
  if (column_names)
2973
3085
  {
2974
 
    drizzle_field_seek(result,0);
 
3086
    drizzle_column_seek(result,0);
2975
3087
    (void) tee_fputs("|", PAGER);
2976
 
    for (uint off=0; (field = drizzle_fetch_field(result)) ; off++)
 
3088
    for (uint32_t off=0; (field = drizzle_column_next(result)) ; off++)
2977
3089
    {
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;
 
3090
      uint32_t name_length= (uint32_t) strlen(drizzle_column_name(field));
 
3091
      uint32_t numcells= charset_info->cset->numcells(charset_info,
 
3092
                                                  drizzle_column_name(field),
 
3093
                                                  drizzle_column_name(field) +
 
3094
                                                  name_length);
 
3095
      uint32_t display_length= drizzle_column_max_size(field) + name_length -
 
3096
                               numcells;
2983
3097
      tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
2984
3098
                                             MAX_COLUMN_LENGTH),
2985
 
                  field->name);
2986
 
      num_flag[off]= ((field->type <= DRIZZLE_TYPE_LONGLONG) || 
2987
 
                      (field->type == DRIZZLE_TYPE_NEWDECIMAL));
 
3099
                  drizzle_column_name(field));
 
3100
      num_flag[off]= ((drizzle_column_type(field) <= DRIZZLE_COLUMN_TYPE_LONGLONG) ||
 
3101
                      (drizzle_column_type(field) == DRIZZLE_COLUMN_TYPE_NEWDECIMAL));
2988
3102
    }
2989
3103
    (void) tee_fputs("\n", PAGER);
2990
3104
    tee_puts((char*) separator.c_str(), PAGER);
2991
3105
  }
2992
3106
 
2993
 
  while ((cur= drizzle_fetch_row(result)))
 
3107
  while (1)
2994
3108
  {
2995
 
    if (interrupted_query)
 
3109
    if (quick)
 
3110
    {
 
3111
      cur= drizzle_row_buffer(result, &ret);
 
3112
      if (ret != DRIZZLE_RETURN_OK)
 
3113
      {
 
3114
        (void)put_error(&con, result);
 
3115
        break;
 
3116
      }
 
3117
    }
 
3118
    else
 
3119
      cur= drizzle_row_next(result);
 
3120
 
 
3121
    if (cur == NULL || interrupted_query)
2996
3122
      break;
2997
 
    uint32_t *lengths= drizzle_fetch_lengths(result);
 
3123
 
 
3124
    size_t *lengths= drizzle_row_field_sizes(result);
2998
3125
    (void) tee_fputs("| ", PAGER);
2999
 
    drizzle_field_seek(result, 0);
3000
 
    for (uint off= 0; off < drizzle_num_fields(result); off++)
 
3126
    drizzle_column_seek(result, 0);
 
3127
    for (uint32_t off= 0; off < drizzle_result_column_count(result); off++)
3001
3128
    {
3002
3129
      const char *buffer;
3003
 
      uint data_length;
3004
 
      uint field_max_length;
3005
 
      uint visible_length;
3006
 
      uint extra_padding;
 
3130
      uint32_t data_length;
 
3131
      uint32_t field_max_length;
 
3132
      uint32_t visible_length;
 
3133
      uint32_t extra_padding;
3007
3134
 
3008
3135
      if (cur[off] == NULL)
3009
3136
      {
3013
3140
      else
3014
3141
      {
3015
3142
        buffer= cur[off];
3016
 
        data_length= (uint) lengths[off];
 
3143
        data_length= (uint32_t) lengths[off];
3017
3144
      }
3018
3145
 
3019
 
      field= drizzle_fetch_field(result);
3020
 
      field_max_length= field->max_length;
 
3146
      field= drizzle_column_next(result);
 
3147
      field_max_length= drizzle_column_max_size(field);
3021
3148
 
3022
3149
      /*
3023
3150
        How many text cells on the screen will this string span?  If it contains
3031
3158
      extra_padding= data_length - visible_length;
3032
3159
 
3033
3160
      if (field_max_length > MAX_COLUMN_LENGTH)
3034
 
        tee_print_sized_data(buffer, data_length, MAX_COLUMN_LENGTH+extra_padding, FALSE);
 
3161
        tee_print_sized_data(buffer, data_length, MAX_COLUMN_LENGTH+extra_padding, false);
3035
3162
      else
3036
3163
      {
3037
3164
        if (num_flag[off] != 0) /* if it is numeric, we right-justify it */
3038
 
          tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, TRUE);
 
3165
          tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, true);
3039
3166
        else
3040
3167
          tee_print_sized_data(buffer, data_length,
3041
 
                               field_max_length+extra_padding, FALSE);
 
3168
                               field_max_length+extra_padding, false);
3042
3169
      }
3043
3170
      tee_fputs(" | ", PAGER);
3044
3171
    }
3045
3172
    (void) tee_fputs("\n", PAGER);
 
3173
    if (quick)
 
3174
      drizzle_row_free(result, cur);
3046
3175
  }
3047
3176
  tee_puts(separator.c_str(), PAGER);
3048
3177
  free(num_flag);
3064
3193
 
3065
3194
   @returns  number of character positions to be used, at most
3066
3195
*/
3067
 
static int get_field_disp_length(DRIZZLE_FIELD *field)
 
3196
static int get_field_disp_length(drizzle_column_st *field)
3068
3197
{
3069
 
  uint length= column_names ? field->name_length : 0;
 
3198
  uint32_t length= column_names ? strlen(drizzle_column_name(field)) : 0;
3070
3199
 
3071
3200
  if (quick)
3072
 
    length= max(length, field->length);
 
3201
    length= max(length, drizzle_column_size(field));
3073
3202
  else
3074
 
    length= max(length, field->max_length);
 
3203
    length= max(length, (uint32_t)drizzle_column_max_size(field));
3075
3204
 
3076
 
  if (length < 4 && !(field->flags & NOT_NULL_FLAG))
 
3205
  if (length < 4 &&
 
3206
    !(drizzle_column_flags(field) & DRIZZLE_COLUMN_FLAGS_NOT_NULL))
 
3207
  {
3077
3208
    length= 4;        /* Room for "NULL" */
 
3209
  }
3078
3210
 
3079
3211
  return length;
3080
3212
}
3087
3219
 
3088
3220
   @returns  The max number of characters in any row of this result
3089
3221
*/
3090
 
static int get_result_width(DRIZZLE_RES *result)
 
3222
static int get_result_width(drizzle_result_st *result)
3091
3223
{
3092
3224
  unsigned int len= 0;
3093
 
  DRIZZLE_FIELD *field;
3094
 
  DRIZZLE_FIELD_OFFSET offset;
 
3225
  drizzle_column_st *field;
 
3226
  uint16_t offset;
3095
3227
 
3096
 
  offset= drizzle_field_tell(result);
 
3228
  offset= drizzle_column_current(result);
3097
3229
  assert(offset == 0);
3098
3230
 
3099
 
  while ((field= drizzle_fetch_field(result)) != NULL)
 
3231
  while ((field= drizzle_column_next(result)) != NULL)
3100
3232
    len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
3101
3233
 
3102
 
  (void) drizzle_field_seek(result, offset);
 
3234
  (void) drizzle_column_seek(result, offset);
3103
3235
 
3104
3236
  return len + 1; /* plus final bar. */
3105
3237
}
3135
3267
 
3136
3268
 
3137
3269
static void
3138
 
print_table_data_vertically(DRIZZLE_RES *result)
 
3270
print_table_data_vertically(drizzle_result_st *result)
3139
3271
{
3140
 
  DRIZZLE_ROW  cur;
3141
 
  uint    max_length=0;
3142
 
  DRIZZLE_FIELD  *field;
 
3272
  drizzle_row_t cur;
 
3273
  drizzle_return_t ret;
 
3274
  uint32_t max_length=0;
 
3275
  drizzle_column_st *field;
3143
3276
 
3144
 
  while ((field = drizzle_fetch_field(result)))
 
3277
  while ((field = drizzle_column_next(result)))
3145
3278
  {
3146
 
    uint length= field->name_length;
 
3279
    uint32_t length= strlen(drizzle_column_name(field));
3147
3280
    if (length > max_length)
3148
3281
      max_length= length;
3149
 
    field->max_length=length;
 
3282
    drizzle_column_set_max_size(field, length);
3150
3283
  }
3151
3284
 
3152
 
  drizzle_field_seek(result,0);
3153
 
  for (uint row_count=1; (cur= drizzle_fetch_row(result)); row_count++)
 
3285
  for (uint32_t row_count=1;; row_count++)
3154
3286
  {
3155
 
    if (interrupted_query)
 
3287
    if (quick)
 
3288
    {
 
3289
      cur= drizzle_row_buffer(result, &ret);
 
3290
      if (ret != DRIZZLE_RETURN_OK)
 
3291
      {
 
3292
        (void)put_error(&con, result);
 
3293
        break;
 
3294
      }
 
3295
    }
 
3296
    else
 
3297
      cur= drizzle_row_next(result);
 
3298
 
 
3299
    if (cur == NULL || interrupted_query)
3156
3300
      break;
3157
 
    drizzle_field_seek(result,0);
 
3301
    drizzle_column_seek(result,0);
3158
3302
    tee_fprintf(PAGER,
3159
3303
                "*************************** %d. row ***************************\n", row_count);
3160
 
    for (uint off=0; off < drizzle_num_fields(result); off++)
 
3304
    for (uint32_t off=0; off < drizzle_result_column_count(result); off++)
3161
3305
    {
3162
 
      field= drizzle_fetch_field(result);
3163
 
      tee_fprintf(PAGER, "%*s: ",(int) max_length,field->name);
 
3306
      field= drizzle_column_next(result);
 
3307
      tee_fprintf(PAGER, "%*s: ",(int) max_length,drizzle_column_name(field));
3164
3308
      tee_fprintf(PAGER, "%s\n",cur[off] ? (char*) cur[off] : "NULL");
3165
3309
    }
 
3310
    if (quick)
 
3311
      drizzle_row_free(result, cur);
3166
3312
  }
3167
3313
}
3168
3314
 
3169
3315
 
3170
3316
/* print_warnings should be called right after executing a statement */
3171
3317
 
3172
 
static void print_warnings()
 
3318
static void print_warnings(uint32_t error_code)
3173
3319
{
3174
 
  const char   *query;
3175
 
  DRIZZLE_RES    *result;
3176
 
  DRIZZLE_ROW    cur;
 
3320
  const char *query;
 
3321
  drizzle_result_st result;
 
3322
  drizzle_row_t cur;
3177
3323
  uint64_t num_rows;
3178
 
 
3179
 
  /* Save current error before calling "show warnings" */
3180
 
  uint error= drizzle_errno(&drizzle);
 
3324
  uint32_t new_code= 0;
3181
3325
 
3182
3326
  /* Get the warnings */
3183
3327
  query= "show warnings";
3184
 
  drizzle_real_query_for_lazy(query, strlen(query));
3185
 
  drizzle_store_result_for_lazy(&result);
 
3328
  drizzleclient_real_query_for_lazy(query, strlen(query),&result,&new_code);
 
3329
  drizzleclient_store_result_for_lazy(&result);
3186
3330
 
3187
3331
  /* Bail out when no warnings */
3188
 
  if (!(num_rows= drizzle_num_rows(result)))
 
3332
  if (!(num_rows= drizzle_result_row_count(&result)))
3189
3333
    goto end;
3190
3334
 
3191
 
  cur= drizzle_fetch_row(result);
 
3335
  cur= drizzle_row_next(&result);
3192
3336
 
3193
3337
  /*
3194
3338
    Don't print a duplicate of the current error.  It is possible for SHOW
3196
3340
    messages.  To be safe, skip printing the duplicate only if it is the only
3197
3341
    warning.
3198
3342
  */
3199
 
  if (!cur || (num_rows == 1 && error == (uint) strtoul(cur[1], NULL, 10)))
 
3343
  if (!cur || (num_rows == 1 &&
 
3344
      error_code == (uint32_t) strtoul(cur[1], NULL, 10)))
 
3345
  {
3200
3346
    goto end;
 
3347
  }
3201
3348
 
3202
3349
  /* Print the warnings */
3203
3350
  init_pager();
3204
3351
  do
3205
3352
  {
3206
3353
    tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]);
3207
 
  } while ((cur= drizzle_fetch_row(result)));
 
3354
  } while ((cur= drizzle_row_next(&result)));
3208
3355
  end_pager();
3209
3356
 
3210
3357
end:
3211
 
  drizzle_free_result(result);
 
3358
  drizzle_result_free(&result);
3212
3359
}
3213
3360
 
3214
3361
 
3222
3369
    if (opt_raw_data)
3223
3370
      tee_fputs(pos, PAGER);
3224
3371
    else for (const char *end=pos+length ; pos != end ; pos++)
3225
 
         {
3226
 
#ifdef USE_MB
3227
 
           int l;
3228
 
           if (use_mb(charset_info) &&
3229
 
               (l = my_ismbchar(charset_info, pos, end)))
3230
 
           {
3231
 
             while (l--)
3232
 
               tee_putc(*pos++, PAGER);
3233
 
             pos--;
3234
 
             continue;
3235
 
           }
3236
 
#endif
3237
 
           if (!*pos)
3238
 
             tee_fputs("\\0", PAGER); // This makes everything hard
3239
 
           else if (*pos == '\t')
3240
 
             tee_fputs("\\t", PAGER); // This would destroy tab format
3241
 
           else if (*pos == '\n')
3242
 
             tee_fputs("\\n", PAGER); // This too
3243
 
           else if (*pos == '\\')
3244
 
             tee_fputs("\\\\", PAGER);
3245
 
           else
3246
 
             tee_putc(*pos, PAGER);
3247
 
         }
 
3372
    {
 
3373
      int l;
 
3374
      if (use_mb(charset_info) &&
 
3375
          (l = my_ismbchar(charset_info, pos, end)))
 
3376
      {
 
3377
        while (l--)
 
3378
          tee_putc(*pos++, PAGER);
 
3379
        pos--;
 
3380
        continue;
 
3381
      }
 
3382
      if (!*pos)
 
3383
        tee_fputs("\\0", PAGER); // This makes everything hard
 
3384
      else if (*pos == '\t')
 
3385
        tee_fputs("\\t", PAGER); // This would destroy tab format
 
3386
      else if (*pos == '\n')
 
3387
        tee_fputs("\\n", PAGER); // This too
 
3388
      else if (*pos == '\\')
 
3389
        tee_fputs("\\\\", PAGER);
 
3390
      else
 
3391
        tee_putc(*pos, PAGER);
 
3392
    }
3248
3393
  }
3249
3394
}
3250
3395
 
3251
3396
 
3252
3397
static void
3253
 
print_tab_data(DRIZZLE_RES *result)
 
3398
print_tab_data(drizzle_result_st *result)
3254
3399
{
3255
 
  DRIZZLE_ROW  cur;
3256
 
  DRIZZLE_FIELD  *field;
3257
 
  uint32_t    *lengths;
 
3400
  drizzle_row_t cur;
 
3401
  drizzle_return_t ret;
 
3402
  drizzle_column_st *field;
 
3403
  size_t *lengths;
3258
3404
 
3259
3405
  if (opt_silent < 2 && column_names)
3260
3406
  {
3261
3407
    int first=0;
3262
 
    while ((field = drizzle_fetch_field(result)))
 
3408
    while ((field = drizzle_column_next(result)))
3263
3409
    {
3264
3410
      if (first++)
3265
3411
        (void) tee_fputs("\t", PAGER);
3266
 
      (void) tee_fputs(field->name, PAGER);
 
3412
      (void) tee_fputs(drizzle_column_name(field), PAGER);
3267
3413
    }
3268
3414
    (void) tee_fputs("\n", PAGER);
3269
3415
  }
3270
 
  while ((cur = drizzle_fetch_row(result)))
 
3416
  while (1)
3271
3417
  {
3272
 
    lengths= drizzle_fetch_lengths(result);
 
3418
    if (quick)
 
3419
    {
 
3420
      cur= drizzle_row_buffer(result, &ret);
 
3421
      if (ret != DRIZZLE_RETURN_OK)
 
3422
      {
 
3423
        (void)put_error(&con, result);
 
3424
        break;
 
3425
      }
 
3426
    }
 
3427
    else
 
3428
      cur= drizzle_row_next(result);
 
3429
 
 
3430
    if (cur == NULL)
 
3431
      break;
 
3432
 
 
3433
    lengths= drizzle_row_field_sizes(result);
3273
3434
    safe_put_field(cur[0],lengths[0]);
3274
 
    for (uint off=1 ; off < drizzle_num_fields(result); off++)
 
3435
    for (uint32_t off=1 ; off < drizzle_result_column_count(result); off++)
3275
3436
    {
3276
3437
      (void) tee_fputs("\t", PAGER);
3277
3438
      safe_put_field(cur[off], lengths[off]);
3278
3439
    }
3279
3440
    (void) tee_fputs("\n", PAGER);
 
3441
    if (quick)
 
3442
      drizzle_row_free(result, cur);
3280
3443
  }
3281
3444
}
3282
3445
 
3283
3446
static int
3284
 
com_tee(string *buffer __attribute__((unused)), const char *line )
 
3447
com_tee(string *, const char *line )
3285
3448
{
3286
 
  char file_name[FN_REFLEN], *end, *param;
 
3449
  char file_name[FN_REFLEN], *end;
 
3450
  const char *param;
3287
3451
 
3288
3452
  if (status.batch)
3289
3453
    return 0;
3308
3472
  /* eliminate the spaces before the parameters */
3309
3473
  while (my_isspace(charset_info,*param))
3310
3474
    param++;
3311
 
  end= strmake(file_name, param, sizeof(file_name) - 1);
 
3475
  strncpy(file_name, param, sizeof(file_name) - 1);
 
3476
  end= file_name + strlen(file_name);
3312
3477
  /* remove end space from command line */
3313
3478
  while (end > file_name && (my_isspace(charset_info,end[-1]) ||
3314
3479
                             my_iscntrl(charset_info,end[-1])))
3325
3490
 
3326
3491
 
3327
3492
static int
3328
 
com_notee(string *buffer __attribute__((unused)),
3329
 
          const char *line __attribute__((unused)))
 
3493
com_notee(string *, const char *)
3330
3494
{
3331
3495
  if (opt_outfile)
3332
3496
    end_tee();
3339
3503
*/
3340
3504
 
3341
3505
static int
3342
 
com_pager(string *buffer __attribute__((unused)),
3343
 
          const char *line __attribute__((unused)))
 
3506
com_pager(string *, const char *line)
3344
3507
{
3345
 
  char pager_name[FN_REFLEN], *end, *param;
 
3508
  char pager_name[FN_REFLEN], *end;
 
3509
  const char *param;
3346
3510
 
3347
3511
  if (status.batch)
3348
3512
    return 0;
3360
3524
    {
3361
3525
      tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
3362
3526
      opt_nopager=1;
3363
 
      my_stpcpy(pager, "stdout");
 
3527
      strcpy(pager, "stdout");
3364
3528
      PAGER= stdout;
3365
3529
      return 0;
3366
3530
    }
3367
 
    my_stpcpy(pager, default_pager);
 
3531
    strcpy(pager, default_pager);
3368
3532
  }
3369
3533
  else
3370
3534
  {
3371
 
    end= strmake(pager_name, param, sizeof(pager_name)-1);
 
3535
    end= strncpy(pager_name, param, sizeof(pager_name)-1);
 
3536
    end+= strlen(pager_name);
3372
3537
    while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
3373
3538
                                my_iscntrl(charset_info,end[-1])))
3374
3539
      end--;
3375
3540
    end[0]=0;
3376
 
    my_stpcpy(pager, pager_name);
3377
 
    my_stpcpy(default_pager, pager_name);
 
3541
    strcpy(pager, pager_name);
 
3542
    strcpy(default_pager, pager_name);
3378
3543
  }
3379
3544
  opt_nopager=0;
3380
3545
  tee_fprintf(stdout, "PAGER set to '%s'\n", pager);
3383
3548
 
3384
3549
 
3385
3550
static int
3386
 
com_nopager(string *buffer __attribute__((unused)),
3387
 
            const char *line __attribute__((unused)))
 
3551
com_nopager(string *, const char *)
3388
3552
{
3389
 
  my_stpcpy(pager, "stdout");
 
3553
  strcpy(pager, "stdout");
3390
3554
  opt_nopager=1;
3391
3555
  PAGER= stdout;
3392
3556
  tee_fprintf(stdout, "PAGER set to stdout\n");
3396
3560
/* If arg is given, exit without errors. This happens on command 'quit' */
3397
3561
 
3398
3562
static int
3399
 
com_quit(string *buffer __attribute__((unused)),
3400
 
         const char *line __attribute__((unused)))
 
3563
com_quit(string *, const char *)
3401
3564
{
3402
3565
  /* let the screen auto close on a normal shutdown */
3403
3566
  status.exit_status=0;
3405
3568
}
3406
3569
 
3407
3570
static int
3408
 
com_rehash(string *buffer __attribute__((unused)),
3409
 
           const char *line __attribute__((unused)))
 
3571
com_rehash(string *, const char *)
3410
3572
{
3411
3573
  build_completion_hash(1, 0);
3412
3574
  return 0;
3415
3577
 
3416
3578
 
3417
3579
static int
3418
 
com_print(string *buffer,const char *line __attribute__((unused)))
 
3580
com_print(string *buffer,const char *)
3419
3581
{
3420
3582
  tee_puts("--------------", stdout);
3421
3583
  (void) tee_fputs(buffer->c_str(), stdout);
3442
3604
      Two null bytes are needed in the end of buff to allow
3443
3605
      get_arg to find end of string the second time it's called.
3444
3606
    */
3445
 
    tmp= strmake(buff, line, sizeof(buff)-2);
 
3607
    tmp= strncpy(buff, line, sizeof(buff)-2);
3446
3608
#ifdef EXTRA_DEBUG
3447
3609
    tmp[1]= 0;
3448
3610
#endif
3461
3623
    else
3462
3624
    {
3463
3625
      /* Quick re-connect */
3464
 
      opt_rehash= 0;                            /* purecov: tested */
 
3626
      opt_rehash= 0;
3465
3627
    }
3466
3628
    // command used
3467
3629
    assert(buffer!=NULL);
3474
3636
 
3475
3637
  if (connected)
3476
3638
  {
3477
 
    sprintf(buff,"Connection id:    %u",drizzle_thread_id(&drizzle));
 
3639
    sprintf(buff,"Connection id:    %u",drizzle_con_thread_id(&con));
3478
3640
    put_info(buff,INFO_INFO,0,0);
3479
3641
    sprintf(buff,"Current database: %.128s\n",
3480
3642
            current_db ? current_db : "*** NONE ***");
3484
3646
}
3485
3647
 
3486
3648
 
3487
 
static int com_source(string *buffer __attribute__((unused)), const char *line)
 
3649
static int com_source(string *, const char *line)
3488
3650
{
3489
 
  char source_name[FN_REFLEN], *end, *param;
3490
 
  LINE_BUFFER *line_buff;
 
3651
  char source_name[FN_REFLEN], *end;
 
3652
  const char *param;
 
3653
  LineBuffer *line_buff;
3491
3654
  int error;
3492
3655
  STATUS old_status;
3493
3656
  FILE *sql_file;
3500
3663
                    INFO_ERROR, 0,0);
3501
3664
  while (my_isspace(charset_info,*param))
3502
3665
    param++;
3503
 
  end=strmake(source_name,param,sizeof(source_name)-1);
 
3666
  end= strncpy(source_name,param,sizeof(source_name)-1);
 
3667
  end+= strlen(source_name);
3504
3668
  while (end > source_name && (my_isspace(charset_info,end[-1]) ||
3505
3669
                               my_iscntrl(charset_info,end[-1])))
3506
3670
    end--;
3507
3671
  end[0]=0;
3508
3672
  unpack_filename(source_name,source_name);
3509
3673
  /* open file name */
3510
 
  if (!(sql_file = my_fopen(source_name, O_RDONLY | O_BINARY,MYF(0))))
 
3674
  if (!(sql_file = fopen(source_name, "r")))
3511
3675
  {
3512
3676
    char buff[FN_REFLEN+60];
3513
3677
    sprintf(buff,"Failed to open file '%s', error: %d", source_name,errno);
3514
3678
    return put_info(buff, INFO_ERROR, 0 ,0);
3515
3679
  }
3516
3680
 
3517
 
  if (!(line_buff=batch_readline_init(opt_max_allowed_packet+512,sql_file)))
 
3681
  line_buff= new(std::nothrow) LineBuffer(opt_max_input_line,sql_file);
 
3682
  if (line_buff == NULL)
3518
3683
  {
3519
 
    my_fclose(sql_file,MYF(0));
3520
 
    return put_info("Can't initialize batch_readline", INFO_ERROR, 0 ,0);
 
3684
    fclose(sql_file);
 
3685
    return put_info("Can't initialize LineBuffer", INFO_ERROR, 0, 0);
3521
3686
  }
3522
3687
 
3523
3688
  /* Save old status */
3534
3699
  error= read_and_execute(false);
3535
3700
  // Continue as before
3536
3701
  status=old_status;
3537
 
  my_fclose(sql_file,MYF(0));
3538
 
  batch_readline_end(line_buff);
 
3702
  fclose(sql_file);
 
3703
  delete status.line_buff;
 
3704
  line_buff= status.line_buff= 0;
3539
3705
  return error;
3540
3706
}
3541
3707
 
3542
3708
 
3543
3709
/* ARGSUSED */
3544
3710
static int
3545
 
com_delimiter(string *buffer __attribute__((unused)), const char *line)
 
3711
com_delimiter(string *, const char *line)
3546
3712
{
3547
3713
  char buff[256], *tmp;
3548
3714
 
3549
 
  strmake(buff, line, sizeof(buff) - 1);
 
3715
  strncpy(buff, line, sizeof(buff) - 1);
3550
3716
  tmp= get_arg(buff, 0);
3551
3717
 
3552
3718
  if (!tmp || !*tmp)
3564
3730
      return 0;
3565
3731
    }
3566
3732
  }
3567
 
  strmake(delimiter, tmp, sizeof(delimiter) - 1);
 
3733
  strncpy(delimiter, tmp, sizeof(delimiter) - 1);
3568
3734
  delimiter_length= (int)strlen(delimiter);
3569
3735
  delimiter_str= delimiter;
3570
3736
  return 0;
3572
3738
 
3573
3739
/* ARGSUSED */
3574
3740
static int
3575
 
com_use(string *buffer __attribute__((unused)), const char *line)
 
3741
com_use(string *, const char *line)
3576
3742
{
3577
3743
  char *tmp, buff[FN_REFLEN + 1];
3578
3744
  int select_db;
 
3745
  drizzle_result_st result;
 
3746
  drizzle_return_t ret;
3579
3747
 
3580
3748
  memset(buff, 0, sizeof(buff));
3581
 
  strmake(buff, line, sizeof(buff) - 1);
 
3749
  strncpy(buff, line, sizeof(buff) - 1);
3582
3750
  tmp= get_arg(buff, 0);
3583
3751
  if (!tmp || !*tmp)
3584
3752
  {
3592
3760
  */
3593
3761
  get_current_db();
3594
3762
 
3595
 
  if (!current_db || cmp_database(charset_info, current_db,tmp))
 
3763
  if (!current_db || strcmp(current_db,tmp))
3596
3764
  {
3597
3765
    if (one_database)
3598
3766
    {
3599
3767
      skip_updates= 1;
3600
 
      select_db= 0;    // don't do drizzle_select_db()
 
3768
      select_db= 0;    // don't do drizzleclient_select_db()
3601
3769
    }
3602
3770
    else
3603
 
      select_db= 2;    // do drizzle_select_db() and build_completion_hash()
 
3771
      select_db= 2;    // do drizzleclient_select_db() and build_completion_hash()
3604
3772
  }
3605
3773
  else
3606
3774
  {
3607
3775
    /*
3608
3776
      USE to the current db specified.
3609
 
      We do need to send drizzle_select_db() to make server
 
3777
      We do need to send drizzleclient_select_db() to make server
3610
3778
      update database level privileges, which might
3611
3779
      change since last USE (see bug#10979).
3612
3780
      For performance purposes, we'll skip rebuilding of completion hash.
3613
3781
    */
3614
3782
    skip_updates= 0;
3615
 
    select_db= 1;      // do only drizzle_select_db(), without completion
 
3783
    select_db= 1;      // do only drizzleclient_select_db(), without completion
3616
3784
  }
3617
3785
 
3618
3786
  if (select_db)
3623
3791
    */
3624
3792
    if (!connected && reconnect())
3625
3793
      return opt_reconnect ? -1 : 1;                        // Fatal error
3626
 
    if (drizzle_select_db(&drizzle,tmp))
 
3794
    for (bool try_again= true; try_again; try_again= false)
3627
3795
    {
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);
 
3796
      if (drizzle_select_db(&con,&result,tmp,&ret) == NULL ||
 
3797
          ret != DRIZZLE_RETURN_OK)
 
3798
      {
 
3799
        if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
3800
        {
 
3801
          int error= put_error(&con, &result);
 
3802
          drizzle_result_free(&result);
 
3803
          return error;
 
3804
        }
 
3805
 
 
3806
        if (ret != DRIZZLE_RETURN_SERVER_GONE || !try_again)
 
3807
          return put_error(&con, NULL);
 
3808
 
 
3809
        if (reconnect())
 
3810
          return opt_reconnect ? -1 : 1;                      // Fatal error
 
3811
      }
 
3812
      else
 
3813
        drizzle_result_free(&result);
3635
3814
    }
3636
3815
    free(current_db);
3637
3816
    current_db= strdup(tmp);
3644
3823
}
3645
3824
 
3646
3825
static int
3647
 
com_warnings(string *buffer __attribute__((unused)),
3648
 
             const char *line __attribute__((unused)))
 
3826
com_warnings(string *, const char *)
3649
3827
{
3650
3828
  show_warnings = 1;
3651
3829
  put_info("Show warnings enabled.",INFO_INFO, 0, 0);
3653
3831
}
3654
3832
 
3655
3833
static int
3656
 
com_nowarnings(string *buffer __attribute__((unused)),
3657
 
               const char *line __attribute__((unused)))
 
3834
com_nowarnings(string *, const char *)
3658
3835
{
3659
3836
  show_warnings = 0;
3660
3837
  put_info("Show warnings disabled.",INFO_INFO, 0, 0);
3710
3887
    if (*ptr == '\\' && ptr[1]) // escaped character
3711
3888
    {
3712
3889
      // Remove the backslash
3713
 
      my_stpcpy(ptr, ptr+1);
 
3890
      strcpy(ptr, ptr+1);
3714
3891
    }
3715
3892
    else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
3716
3893
    {
3725
3902
 
3726
3903
static int
3727
3904
sql_connect(char *host,char *database,char *user,char *password,
3728
 
                 uint silent)
 
3905
                 uint32_t silent)
3729
3906
{
 
3907
  drizzle_return_t ret;
 
3908
 
3730
3909
  if (connected)
3731
3910
  {
3732
3911
    connected= 0;
3733
 
    drizzle_close(&drizzle);
 
3912
    drizzle_con_free(&con);
 
3913
    drizzle_free(&drizzle);
3734
3914
  }
3735
3915
  drizzle_create(&drizzle);
 
3916
  if (drizzle_con_add_tcp(&drizzle, &con, host, opt_drizzle_port, user,
 
3917
                          password, database, DRIZZLE_CON_NONE) == NULL)
 
3918
  {
 
3919
    (void) put_error(&con, NULL);
 
3920
    (void) fflush(stdout);
 
3921
    return 1;
 
3922
  }
 
3923
 
 
3924
/* XXX add this back in
3736
3925
  if (opt_connect_timeout)
3737
3926
  {
3738
 
    uint timeout=opt_connect_timeout;
3739
 
    drizzle_options(&drizzle,DRIZZLE_OPT_CONNECT_TIMEOUT,
 
3927
    uint32_t timeout=opt_connect_timeout;
 
3928
    drizzleclient_options(&drizzle,DRIZZLE_OPT_CONNECT_TIMEOUT,
3740
3929
                  (char*) &timeout);
3741
3930
  }
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);
 
3931
*/
 
3932
 
 
3933
/* XXX Do we need this?
3748
3934
  if (safe_updates)
3749
3935
  {
3750
3936
    char init_command[100];
3751
3937
    sprintf(init_command,
3752
3938
            "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%"PRIu32
3753
 
            ",SQL_MAX_JOIN_SIZE=%"PRIu32,
 
3939
            ",MAX_JOIN_SIZE=%"PRIu32,
3754
3940
            select_limit, max_join_size);
3755
 
    drizzle_options(&drizzle, DRIZZLE_INIT_COMMAND, init_command);
 
3941
    drizzleclient_options(&drizzle, DRIZZLE_INIT_COMMAND, init_command);
3756
3942
  }
3757
 
  if (!drizzle_connect(&drizzle, host, user, password,
3758
 
                          database, opt_drizzle_port, opt_drizzle_unix_port,
3759
 
                          connect_flag | CLIENT_MULTI_STATEMENTS))
 
3943
*/
 
3944
  if ((ret= drizzle_con_connect(&con)) != DRIZZLE_RETURN_OK)
3760
3945
  {
3761
 
    if (!silent ||
3762
 
        (drizzle_errno(&drizzle) != CR_CONN_HOST_ERROR &&
3763
 
         drizzle_errno(&drizzle) != CR_CONNECTION_ERROR))
 
3946
    if (!silent || (ret != DRIZZLE_RETURN_GETADDRINFO &&
 
3947
                    ret != DRIZZLE_RETURN_COULD_NOT_CONNECT))
3764
3948
    {
3765
 
      (void) put_error(&drizzle);
 
3949
      (void) put_error(&con, NULL);
3766
3950
      (void) fflush(stdout);
3767
3951
      return ignore_errors ? -1 : 1;    // Abort
3768
3952
    }
3769
3953
    return -1;          // Retryable
3770
3954
  }
3771
3955
  connected=1;
 
3956
/* XXX hmm?
3772
3957
  drizzle.reconnect= debug_info_flag; // We want to know if this happens
 
3958
*/
3773
3959
  build_completion_hash(opt_rehash, 1);
3774
3960
  return 0;
3775
3961
}
3776
3962
 
3777
3963
 
3778
3964
static int
3779
 
com_status(string *buffer __attribute__((unused)),
3780
 
           const char *line __attribute__((unused)))
 
3965
com_status(string *, const char *)
3781
3966
{
 
3967
/*
3782
3968
  char buff[40];
3783
3969
  uint64_t id;
3784
 
  DRIZZLE_RES *result;
 
3970
*/
 
3971
  drizzle_result_st result;
 
3972
  drizzle_return_t ret;
3785
3973
 
3786
3974
  tee_puts("--------------", stdout);
3787
3975
  usage(1);          /* Print version */
3788
3976
  if (connected)
3789
3977
  {
3790
 
    tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",drizzle_thread_id(&drizzle));
 
3978
    tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",drizzle_con_thread_id(&con));
3791
3979
    /*
3792
3980
      Don't remove "limit 1",
3793
3981
      it is protection againts SQL_SELECT_LIMIT=0
3794
3982
    */
3795
 
    if (!drizzle_query(&drizzle,"select DATABASE(), USER() limit 1") &&
3796
 
        (result=drizzle_use_result(&drizzle)))
 
3983
    if (drizzle_query_str(&con,&result,"select DATABASE(), USER() limit 1",
 
3984
                          &ret) != NULL && ret == DRIZZLE_RETURN_OK &&
 
3985
        drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
3797
3986
    {
3798
 
      DRIZZLE_ROW cur=drizzle_fetch_row(result);
 
3987
      drizzle_row_t cur=drizzle_row_next(&result);
3799
3988
      if (cur)
3800
3989
      {
3801
3990
        tee_fprintf(stdout, "Current database:\t%s\n", cur[0] ? cur[0] : "");
3802
3991
        tee_fprintf(stdout, "Current user:\t\t%s\n", cur[1]);
3803
3992
      }
3804
 
      drizzle_free_result(result);
 
3993
      drizzle_result_free(&result);
3805
3994
    }
 
3995
    else if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
3996
      drizzle_result_free(&result);
3806
3997
    tee_puts("SSL:\t\t\tNot in use", stdout);
3807
3998
  }
3808
3999
  else
3821
4012
  tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
3822
4013
  tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
3823
4014
  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)))
 
4015
  tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&con));
 
4016
  tee_fprintf(stdout, "Protocol version:\t%d\n", drizzle_con_protocol_version(&con));
 
4017
  tee_fprintf(stdout, "Connection:\t\t%s\n", drizzle_con_host(&con));
 
4018
/* XXX need to save this from result
 
4019
  if ((id= drizzleclient_insert_id(&drizzle)))
3828
4020
    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);
 
4021
*/
 
4022
 
 
4023
  if (strcmp(drizzle_con_uds(&con), ""))
 
4024
    tee_fprintf(stdout, "UNIX socket:\t\t%s\n", drizzle_con_uds(&con));
3847
4025
  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");
 
4026
    tee_fprintf(stdout, "TCP port:\t\t%d\n", drizzle_con_port(&con));
3851
4027
 
3852
4028
  if (safe_updates)
3853
4029
  {
3866
4042
}
3867
4043
 
3868
4044
static const char *
3869
 
server_version_string(DRIZZLE *con)
 
4045
server_version_string(drizzle_con_st *local_con)
3870
4046
{
3871
 
  static char buf[MAX_SERVER_VERSION_LENGTH] = "";
 
4047
  static string buf("");
 
4048
  static bool server_version_string_reserved= false;
3872
4049
 
 
4050
  if (!server_version_string_reserved)
 
4051
  {
 
4052
    buf.reserve(MAX_SERVER_VERSION_LENGTH);
 
4053
    server_version_string_reserved= true;
 
4054
  }
3873
4055
  /* Only one thread calls this, so no synchronization is needed */
3874
4056
  if (buf[0] == '\0')
3875
4057
  {
3876
 
    char *bufp = buf;
3877
 
    DRIZZLE_RES *result;
 
4058
    drizzle_result_st result;
 
4059
    drizzle_return_t ret;
3878
4060
 
3879
 
    bufp= my_stpncpy(buf, drizzle_get_server_info(con), sizeof buf);
 
4061
    buf.append(drizzle_con_server_version(local_con));
3880
4062
 
3881
4063
    /* "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)))
 
4064
    (void)drizzle_query_str(local_con, &result,
 
4065
                            "select @@version_comment limit 1", &ret);
 
4066
    if (ret == DRIZZLE_RETURN_OK &&
 
4067
        drizzle_result_buffer(&result) == DRIZZLE_RETURN_OK)
3884
4068
    {
3885
 
      DRIZZLE_ROW cur = drizzle_fetch_row(result);
 
4069
      drizzle_row_t cur = drizzle_row_next(&result);
3886
4070
      if (cur && cur[0])
3887
4071
      {
3888
 
        bufp = strxnmov(bufp, sizeof buf - (bufp - buf), " ", cur[0], NULL);
 
4072
        buf.append(" ");
 
4073
        buf.append(cur[0]);
3889
4074
      }
3890
 
      drizzle_free_result(result);
 
4075
      drizzle_result_free(&result);
3891
4076
    }
3892
 
 
3893
 
    /* str*nmov doesn't guarantee NUL-termination */
3894
 
    if (bufp == buf + sizeof buf)
3895
 
      buf[sizeof buf - 1] = '\0';
 
4077
    else if (ret == DRIZZLE_RETURN_ERROR_CODE)
 
4078
      drizzle_result_free(&result);
3896
4079
  }
3897
4080
 
3898
 
  return buf;
 
4081
  return buf.c_str();
3899
4082
}
3900
4083
 
3901
4084
static int
3902
 
put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
 
4085
put_info(const char *str,INFO_TYPE info_type, uint32_t error, const char *sqlstate)
3903
4086
{
3904
4087
  FILE *file= (info_type == INFO_ERROR ? stderr : stdout);
3905
4088
  static int inited=0;
3971
4154
 
3972
4155
 
3973
4156
static int
3974
 
put_error(DRIZZLE *con)
 
4157
put_error(drizzle_con_st *local_con, drizzle_result_st *res)
3975
4158
{
3976
 
  return put_info(drizzle_error(con), INFO_ERROR, drizzle_errno(con),
3977
 
                  drizzle_sqlstate(con));
 
4159
  const char *error;
 
4160
 
 
4161
  if (res != NULL)
 
4162
  {
 
4163
    error= drizzle_result_error(res);
 
4164
    if (!strcmp(error, ""))
 
4165
      error= drizzle_con_error(local_con);
 
4166
  }
 
4167
  else
 
4168
    error= drizzle_con_error(local_con);
 
4169
 
 
4170
  return put_info(error, INFO_ERROR,
 
4171
                  res == NULL ? drizzle_con_error_code(local_con) :
 
4172
                                drizzle_result_error_code(res),
 
4173
                  res == NULL ? drizzle_con_sqlstate(local_con) :
 
4174
                                drizzle_result_sqlstate(res));
3978
4175
}
3979
4176
 
3980
4177
 
3984
4181
  const char *end= start + (buffer->length());
3985
4182
  while (start < end && !my_isgraph(charset_info,end[-1]))
3986
4183
    end--;
3987
 
  uint pos_to_truncate= (end-start);
 
4184
  uint32_t pos_to_truncate= (end-start);
3988
4185
  if (buffer->length() > pos_to_truncate)
3989
4186
    buffer->erase(pos_to_truncate);
3990
4187
}
4055
4252
static void nice_time(double sec,char *buff,bool part_second)
4056
4253
{
4057
4254
  uint32_t tmp;
 
4255
  ostringstream tmp_buff_str;
 
4256
 
4058
4257
  if (sec >= 3600.0*24)
4059
4258
  {
4060
4259
    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 ");
 
4260
    sec-= 3600.0*24*tmp;
 
4261
    tmp_buff_str << tmp;
 
4262
 
 
4263
    if (tmp > 1)
 
4264
      tmp_buff_str << " days ";
 
4265
    else
 
4266
      tmp_buff_str << " day ";
 
4267
 
4064
4268
  }
4065
4269
  if (sec >= 3600.0)
4066
4270
  {
4067
4271
    tmp=(uint32_t) floor(sec/3600.0);
4068
4272
    sec-=3600.0*tmp;
4069
 
    buff=int10_to_str((long) tmp, buff, 10);
4070
 
    buff=my_stpcpy(buff,tmp > 1 ? " hours " : " hour ");
 
4273
    tmp_buff_str << tmp;
 
4274
 
 
4275
    if (tmp > 1)
 
4276
      tmp_buff_str << " hours ";
 
4277
    else
 
4278
      tmp_buff_str << " hour ";
4071
4279
  }
4072
4280
  if (sec >= 60.0)
4073
4281
  {
4074
4282
    tmp=(uint32_t) floor(sec/60.0);
4075
4283
    sec-=60.0*tmp;
4076
 
    buff=int10_to_str((long) tmp, buff, 10);
4077
 
    buff=my_stpcpy(buff," min ");
 
4284
    tmp_buff_str << tmp << " min ";
4078
4285
  }
4079
4286
  if (part_second)
4080
 
    sprintf(buff,"%.2f sec",sec);
 
4287
    tmp_buff_str.precision(2);
4081
4288
  else
4082
 
    sprintf(buff,"%d sec",(int) sec);
 
4289
    tmp_buff_str.precision(0);
 
4290
  tmp_buff_str << sec << " sec";
 
4291
  strcpy(buff, tmp_buff_str.str().c_str());
4083
4292
}
4084
4293
 
4085
4294
 
4095
4304
  buff[0]=' ';
4096
4305
  buff[1]='(';
4097
4306
  end_timer(start_time,buff+2);
4098
 
  my_stpcpy(strchr(buff, '\0'),")");
 
4307
  strcpy(strchr(buff, '\0'),")");
4099
4308
}
4100
4309
 
4101
4310
static const char * construct_prompt()
4119
4328
    {
4120
4329
      int getHour;
4121
4330
      int getYear;
4122
 
      char* dateTime= NULL;
 
4331
      /* Room for Dow MMM DD HH:MM:SS YYYY */ 
 
4332
      char dateTime[32];
4123
4333
      switch (*++c) {
4124
4334
      case '\0':
4125
4335
        // stop it from going beyond if ends with %
4130
4340
        break;
4131
4341
      case 'v':
4132
4342
        if (connected)
4133
 
          processed_prompt->append(drizzle_get_server_info(&drizzle));
 
4343
          processed_prompt->append(drizzle_con_server_version(&con));
4134
4344
        else
4135
4345
          processed_prompt->append("not_connected");
4136
4346
        break;
4140
4350
      case 'h':
4141
4351
      {
4142
4352
        const char *prompt;
4143
 
        prompt= connected ? drizzle_get_host_info(&drizzle) : "not_connected";
 
4353
        prompt= connected ? drizzle_con_host(&con) : "not_connected";
4144
4354
        if (strstr(prompt, "Localhost"))
4145
4355
          processed_prompt->append("localhost");
4146
4356
        else
4159
4369
          break;
4160
4370
        }
4161
4371
 
4162
 
        const char *host_info = drizzle_get_host_info(&drizzle);
4163
 
        if (strstr(host_info, "memory"))
 
4372
        if (strcmp(drizzle_con_uds(&con), ""))
4164
4373
        {
4165
 
          processed_prompt->append(drizzle.host);
 
4374
          const char *pos=strrchr(drizzle_con_uds(&con),'/');
 
4375
          processed_prompt->append(pos ? pos+1 : drizzle_con_uds(&con));
4166
4376
        }
4167
 
        else if (strstr(host_info,"TCP/IP") ||
4168
 
                 !drizzle.unix_socket)
4169
 
          add_int_to_prompt(drizzle.port);
4170
4377
        else
4171
 
        {
4172
 
          char *pos=strrchr(drizzle.unix_socket,'/');
4173
 
          processed_prompt->append(pos ? pos+1 : drizzle.unix_socket);
4174
 
        }
 
4378
          add_int_to_prompt(drizzle_con_port(&con));
4175
4379
      }
4176
4380
      break;
4177
4381
      case 'U':
4188
4392
        break;
4189
4393
      case PROMPT_CHAR:
4190
4394
        {
4191
 
          char c= PROMPT_CHAR;
4192
 
          processed_prompt->append(&c, 1);
 
4395
          processed_prompt->append(PROMPT_CHAR, 1);
4193
4396
        }
4194
4397
        break;
4195
4398
      case 'n':
4196
4399
        {
4197
 
          char c= '\n';
4198
 
          processed_prompt->append(&c, 1);
 
4400
          processed_prompt->append('\n', 1);
4199
4401
        }
4200
4402
        break;
4201
4403
      case ' ':
4202
4404
      case '_':
4203
4405
        {
4204
 
          char c= ' ';
4205
 
          processed_prompt->append(&c, 1);
 
4406
          processed_prompt->append(' ', 1);
4206
4407
        }
4207
4408
        break;
4208
4409
      case 'R':
4233
4434
        add_int_to_prompt(t->tm_year+1900);
4234
4435
        break;
4235
4436
      case 'D':
4236
 
        dateTime = ctime(&lclock);
4237
 
        processed_prompt->append(strtok(dateTime,"\n"));
 
4437
        strftime(dateTime, 32, "%a %b %d %H:%M:%S %Y", localtime(&lclock));
 
4438
        processed_prompt->append(dateTime);
4238
4439
        break;
4239
4440
      case 's':
4240
4441
        if (t->tm_sec < 10)
4279
4480
 
4280
4481
static void add_int_to_prompt(int toadd)
4281
4482
{
4282
 
  char buffer[16];
4283
 
  int10_to_str(toadd, buffer, 10);
4284
 
  processed_prompt->append(buffer);
 
4483
  ostringstream buffer;
 
4484
  buffer << toadd;
 
4485
  processed_prompt->append(buffer.str().c_str());
4285
4486
}
4286
4487
 
4287
4488
static void init_username()
4288
4489
{
 
4490
/* XXX need this?
4289
4491
  free(full_username);
4290
4492
  free(part_username);
4291
4493
 
4292
 
  DRIZZLE_RES *result;
4293
 
  if (!drizzle_query(&drizzle,"select USER()") &&
4294
 
      (result=drizzle_use_result(&drizzle)))
 
4494
  drizzle_result_st *result;
 
4495
  if (!drizzleclient_query(&drizzle,"select USER()") &&
 
4496
      (result=drizzleclient_use_result(&drizzle)))
4295
4497
  {
4296
 
    DRIZZLE_ROW cur=drizzle_fetch_row(result);
 
4498
    drizzle_row_t cur=drizzleclient_fetch_row(result);
4297
4499
    full_username= strdup(cur[0]);
4298
4500
    part_username= strdup(strtok(cur[0],"@"));
4299
 
    (void) drizzle_fetch_row(result);        // Read eof
 
4501
    (void) drizzleclient_fetch_row(result);        // Read eof
4300
4502
  }
 
4503
*/
4301
4504
}
4302
4505
 
4303
 
static int com_prompt(string *buffer __attribute__((unused)),
4304
 
                      const char *line)
 
4506
static int com_prompt(string *, const char *line)
4305
4507
{
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)
 
4508
  const char *ptr=strchr(line, ' ');
 
4509
  if (ptr == NULL)
4311
4510
    tee_fprintf(stdout, "Returning to default PROMPT of %s\n",
4312
4511
                default_prompt);
 
4512
  prompt_counter = 0;
 
4513
  char * tmpptr= strdup(ptr ? ptr+1 : default_prompt);
 
4514
  if (tmpptr == NULL)
 
4515
    tee_fprintf(stdout, "Memory allocation error. Not changing prompt\n");
4313
4516
  else
 
4517
  {
 
4518
    free(current_prompt);
 
4519
    current_prompt= tmpptr;
4314
4520
    tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
 
4521
  }
4315
4522
  return 0;
4316
4523
}
4317
4524