~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzle.cc

  • Committer: Brian Aker
  • Date: 2009-01-21 05:53:36 UTC
  • mto: This revision was merged to the branch mainline in revision 801.
  • Revision ID: brian@tangent.org-20090121055336-fxoz6wfzreo8gi9x
Removed purge

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 *
34
34
 **/
35
35
 
 
36
#include "client_priv.h"
36
37
#include <string>
37
 
 
38
 
#include "client_priv.h"
 
38
#include CMATH_H
 
39
#include <algorithm>
39
40
#include <mystrings/m_ctype.h>
40
41
#include <stdarg.h>
41
 
#ifndef __GNU_LIBRARY__
42
 
#define __GNU_LIBRARY__          // Skip warnings in getopt.h
43
 
#endif
44
 
#include <readline/history.h>
45
42
#include "my_readline.h"
46
43
#include <signal.h>
47
 
#include <vio/violite.h>
48
44
#include <sys/ioctl.h>
49
 
 
50
 
 
51
 
#if defined(HAVE_LOCALE_H)
52
 
#include <locale.h>
53
 
#endif
54
 
 
55
 
#include <libdrizzle/gettext.h>
56
 
 
57
 
const char *VER= "14.14";
58
 
 
59
 
/* Don't try to make a nice table if the data is too big */
60
 
#define MAX_COLUMN_LENGTH       (uint32_t)1024
61
 
 
62
 
/* Buffer to hold 'version' and 'version_comment' */
63
 
#define MAX_SERVER_VERSION_LENGTH     128
64
 
 
65
 
/* Array of options to pass to libdrizzled */
66
 
#define MAX_SERVER_ARGS               64
67
 
 
68
 
void* sql_alloc(unsigned size);       // Don't use drizzled alloc for these
69
 
void sql_element_free(void *ptr);
 
45
#include <drizzled/configmake.h>
70
46
 
71
47
#if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
72
48
#include <curses.h>
 
49
#ifdef __sun
 
50
#undef clear
 
51
#undef erase
 
52
#endif
73
53
#include <term.h>
74
54
#else
75
55
#if defined(HAVE_TERMIOS_H)
80
60
#elif defined(HAVE_ASM_TERMBITS_H) && (!defined __GLIBC__ || !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ > 0))
81
61
#include <asm/termbits.h>    // Standard linux
82
62
#endif
83
 
#undef VOID
84
63
#if defined(HAVE_TERMCAP_H)
85
64
#include <termcap.h>
86
65
#else
94
73
#endif
95
74
#endif
96
75
 
97
 
#undef bcmp                             // Fix problem with new readline
 
76
#ifdef HAVE_LIBREADLINE
 
77
#  if defined(HAVE_READLINE_READLINE_H)
 
78
#    include <readline/readline.h>
 
79
#  elif defined(HAVE_READLINE_H)
 
80
#    include <readline.h>
 
81
#  else /* !defined(HAVE_READLINE_H) */
 
82
extern char *readline ();
 
83
#  endif /* !defined(HAVE_READLINE_H) */
 
84
char *cmdline = NULL;
 
85
#else /* !defined(HAVE_READLINE_READLINE_H) */
 
86
  /* no readline */
 
87
#  error Readline Required
 
88
#endif /* HAVE_LIBREADLINE */
98
89
 
99
 
#ifdef HAVE_READLINE_HISTORY_H
100
 
#include <readline/history.h>
101
 
#endif
102
 
#include <readline/readline.h>
 
90
#ifdef HAVE_READLINE_HISTORY
 
91
#  if defined(HAVE_READLINE_HISTORY_H)
 
92
#    include <readline/history.h>
 
93
#  elif defined(HAVE_HISTORY_H)
 
94
#    include <history.h>
 
95
#  else /* !defined(HAVE_HISTORY_H) */
 
96
extern void add_history ();
 
97
extern int write_history ();
 
98
extern int read_history ();
 
99
#  endif /* defined(HAVE_READLINE_HISTORY_H) */
 
100
    /* no history */
 
101
#endif /* HAVE_READLINE_HISTORY */
103
102
 
104
103
/**
105
104
 Make the old readline interface look like the new one.
111
110
  completion_matches((char *)str, (CPFunction *)func)
112
111
#endif
113
112
 
 
113
#if defined(HAVE_LOCALE_H)
 
114
#include <locale.h>
 
115
#endif
 
116
 
 
117
#include <drizzled/gettext.h>
 
118
 
 
119
#if defined(CMATH_NAMESPACE)
 
120
  using namespace CMATH_NAMESPACE;
 
121
#endif
 
122
 
 
123
const char *VER= "14.14";
 
124
 
 
125
/* Don't try to make a nice table if the data is too big */
 
126
#define MAX_COLUMN_LENGTH       (uint32_t)1024
 
127
 
 
128
/* Buffer to hold 'version' and 'version_comment' */
 
129
#define MAX_SERVER_VERSION_LENGTH     128
 
130
 
 
131
void* sql_alloc(unsigned size);       // Don't use drizzled alloc for these
 
132
void sql_element_free(void *ptr);
 
133
 
114
134
 
115
135
#if !defined(HAVE_VIDATTR)
116
136
#undef vidattr
147
167
typedef enum enum_info_type INFO_TYPE;
148
168
 
149
169
static DRIZZLE drizzle;      /* The connection */
150
 
static bool ignore_errors=0,quick=0,
151
 
  connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
152
 
  opt_rehash=1,skip_updates=0,safe_updates=0,one_database=0,
153
 
  opt_compress=0, using_opt_local_infile=0,
154
 
  vertical=0, line_numbers=1, column_names=1,
155
 
  opt_nopager=1, opt_outfile=0, named_cmds= 0,
156
 
  tty_password= 0, opt_nobeep=0, opt_reconnect=1,
157
 
  default_charset_used= 0, opt_secure_auth= 0,
158
 
  default_pager_set= 0, opt_sigint_ignore= 0,
159
 
  auto_vertical_output= 0,
160
 
  show_warnings= 0, executing_query= 0, interrupted_query= 0;
 
170
static bool ignore_errors= false, quick= false,
 
171
  connected= false, opt_raw_data= false, unbuffered= false,
 
172
  output_tables= false, opt_rehash= true, skip_updates= false,
 
173
  safe_updates= false, one_database= false,
 
174
  opt_compress= false, using_opt_local_infile= false,
 
175
  vertical= false, line_numbers= true, column_names= true,
 
176
  opt_nopager= true, opt_outfile= false, named_cmds= false,
 
177
  tty_password= false, opt_nobeep= false, opt_reconnect= true,
 
178
  default_charset_used= false, opt_secure_auth= false,
 
179
  default_pager_set= false, opt_sigint_ignore= false,
 
180
  auto_vertical_output= false,
 
181
  show_warnings= false, executing_query= false, interrupted_query= false;
 
182
static uint32_t  show_progress_size= 0;
161
183
static bool debug_info_flag, debug_check_flag;
162
184
static bool column_types_flag;
163
 
static bool preserve_comments= 0;
164
 
static uint32_t opt_max_allowed_packet, opt_net_buffer_length;
165
 
static int verbose=0,opt_silent=0,opt_drizzle_port=0, opt_local_infile=0;
 
185
static bool preserve_comments= false;
 
186
static uint32_t opt_max_allowed_packet, opt_net_buffer_length,
 
187
  opt_drizzle_port= 0;
 
188
static int verbose= 0, opt_silent= 0, opt_local_infile= 0;
166
189
static uint my_end_arg;
167
 
static char * opt_drizzle_unix_port=0;
168
 
static int connect_flag=CLIENT_INTERACTIVE;
169
 
static char *current_host,*current_db,*current_user=0,*opt_password=0,
170
 
  *delimiter_str= 0,* current_prompt= 0,
171
 
  *default_charset= (char*) DRIZZLE_DEFAULT_CHARSET_NAME;
 
190
static char * opt_drizzle_unix_port= NULL;
 
191
static int connect_flag= CLIENT_INTERACTIVE;
 
192
static char *current_host, *current_db, *current_user= NULL,
 
193
  *opt_password= NULL, *delimiter_str= NULL, *current_prompt= NULL;
172
194
static char *histfile;
173
195
static char *histfile_tmp;
174
196
static string *glob_buffer;
175
197
static string *processed_prompt= NULL;
176
198
static char *default_prompt= NULL;
177
 
static char *full_username=0,*part_username=0;
 
199
static char *full_username= NULL,*part_username= NULL;
178
200
static STATUS status;
179
201
static uint32_t select_limit;
180
202
static uint32_t max_join_size;
181
203
static uint32_t opt_connect_timeout= 0;
182
204
static char drizzle_charsets_dir[FN_REFLEN+1];
183
205
// TODO: Need to i18n these
184
 
static const char *day_names[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
185
 
static const char *month_names[]={"Jan","Feb","Mar","Apr","May","Jun","Jul",
 
206
static const char *day_names[]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
 
207
static const char *month_names[]= {"Jan","Feb","Mar","Apr","May","Jun","Jul",
186
208
                                  "Aug","Sep","Oct","Nov","Dec"};
187
209
static char default_pager[FN_REFLEN];
188
210
static char pager[FN_REFLEN], outfile[FN_REFLEN];
193
215
static uint delimiter_length= 1;
194
216
unsigned short terminal_width= 80;
195
217
 
196
 
static uint opt_protocol= DRIZZLE_PROTOCOL_TCP;
197
 
static const CHARSET_INFO *charset_info= &my_charset_latin1;
 
218
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
198
219
 
199
220
int drizzle_real_query_for_lazy(const char *buf, int length);
200
221
int drizzle_store_result_for_lazy(DRIZZLE_RES **result);
207
228
static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
208
229
/* The names of functions that actually do the manipulation. */
209
230
static int get_options(int argc,char **argv);
210
 
bool get_one_option(int optid, const struct my_option *opt,
211
 
                    char *argument);
 
231
extern "C" bool get_one_option(int optid, const struct my_option *opt,
 
232
                               char *argument);
212
233
static int com_quit(string *str,const char*),
213
234
  com_go(string *str,const char*), com_ego(string *str,const char*),
214
235
  com_print(string *str,const char*),
216
237
  com_connect(string *str,const char*), com_status(string *str,const char*),
217
238
  com_use(string *str,const char*), com_source(string *str, const char*),
218
239
  com_rehash(string *str, const char*), com_tee(string *str, const char*),
219
 
  com_notee(string *str, const char*), com_charset(string *str,const char*),
 
240
  com_notee(string *str, const char*),
220
241
  com_prompt(string *str, const char*), com_delimiter(string *str, const char*),
221
242
  com_warnings(string *str, const char*), com_nowarnings(string *str, const char*),
222
243
  com_nopager(string *str, const char*), com_pager(string *str, const char*);
279
300
    N_("Set outfile [to_outfile]. Append everything into given outfile.") },
280
301
  { "use",    'u', com_use,    1,
281
302
    N_("Use another database. Takes database name as argument.") },
282
 
  { "charset",    'C', com_charset,    1,
283
 
    N_("Switch to another charset. Might be needed for processing binlog with multi-byte charsets.") },
284
303
  { "warnings", 'W', com_warnings,  0,
285
304
    N_("Show warnings after every statement.") },
286
305
  { "nowarning", 'w', com_nowarnings, 0,
609
628
  { "QUARTER", 0, 0, 0, ""},
610
629
  { "QUERY", 0, 0, 0, ""},
611
630
  { "QUICK", 0, 0, 0, ""},
612
 
  { "RAID0", 0, 0, 0, ""},
613
 
  { "RAID_CHUNKS", 0, 0, 0, ""},
614
 
  { "RAID_CHUNKSIZE", 0, 0, 0, ""},
615
 
  { "RAID_TYPE", 0, 0, 0, ""},
616
631
  { "READ", 0, 0, 0, ""},
617
632
  { "READS", 0, 0, 0, ""},
618
633
  { "REAL", 0, 0, 0, ""},
1014
1029
static void end_timer(uint32_t start_time,char *buff);
1015
1030
static void drizzle_end_timer(uint32_t start_time,char *buff);
1016
1031
static void nice_time(double sec,char *buff,bool part_second);
1017
 
extern sig_handler drizzle_end(int sig);
1018
 
extern sig_handler handle_sigint(int sig);
 
1032
extern "C" void drizzle_end(int sig);
 
1033
extern "C" void handle_sigint(int sig);
1019
1034
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1020
 
static sig_handler window_resize(int sig);
 
1035
static void window_resize(int sig);
1021
1036
#endif
1022
1037
 
1023
1038
int main(int argc,char *argv[])
1034
1049
 
1035
1050
  MY_INIT(argv[0]);
1036
1051
  delimiter_str= delimiter;
1037
 
  default_prompt= my_strdup(getenv("DRIZZLE_PS1") ?
1038
 
                            getenv("DRIZZLE_PS1") :
1039
 
                            "drizzle>> ", MYF(0));
1040
 
  current_prompt= my_strdup(default_prompt, MYF(0));
 
1052
  default_prompt= strdup(getenv("DRIZZLE_PS1") ?
 
1053
                         getenv("DRIZZLE_PS1") :
 
1054
                         "drizzle> ");
 
1055
  
 
1056
  if (default_prompt == NULL)
 
1057
  {
 
1058
    fprintf(stderr, _("Memory allocation error while constructing initial "
 
1059
                      "prompt. Aborting.\n"));
 
1060
    exit(ENOMEM);
 
1061
  }
 
1062
  current_prompt= strdup(default_prompt);
 
1063
  if (current_prompt == NULL)
 
1064
  {
 
1065
    fprintf(stderr, _("Memory allocation error while constructing initial "
 
1066
                      "prompt. Aborting.\n"));
 
1067
    exit(ENOMEM);
 
1068
  }
1041
1069
  processed_prompt= new string();
1042
1070
  processed_prompt->reserve(32);
1043
1071
 
1044
1072
  prompt_counter=0;
1045
1073
 
1046
1074
  outfile[0]=0;      // no (default) outfile
1047
 
  stpcpy(pager, "stdout");  // the default, if --pager wasn't given
 
1075
  strcpy(pager, "stdout");  // the default, if --pager wasn't given
1048
1076
  {
1049
1077
    char *tmp=getenv("PAGER");
1050
1078
    if (tmp && strlen(tmp))
1051
1079
    {
1052
1080
      default_pager_set= 1;
1053
 
      stpcpy(default_pager, tmp);
 
1081
      strcpy(default_pager, tmp);
1054
1082
    }
1055
1083
  }
1056
1084
  if (!isatty(0) || !isatty(1))
1076
1104
      close(stdout_fileno_copy);             /* Clean up dup(). */
1077
1105
  }
1078
1106
 
1079
 
  load_defaults("my",load_default_groups,&argc,&argv);
 
1107
  load_defaults("drizzle",load_default_groups,&argc,&argv);
1080
1108
  defaults_argv=argv;
1081
1109
  if (get_options(argc, (char **) argv))
1082
1110
  {
1122
1150
 
1123
1151
  glob_buffer= new string();
1124
1152
  glob_buffer->reserve(512);
1125
 
  
 
1153
 
1126
1154
  char * output_buff= (char *)malloc(512);
1127
1155
  memset(output_buff, '\0', 512);
1128
1156
 
1140
1168
      histfile= strdup(getenv("DRIZZLE_HISTFILE"));
1141
1169
    else if (getenv("HOME"))
1142
1170
    {
1143
 
      histfile=(char*) my_malloc((uint) strlen(getenv("HOME"))
1144
 
                                 + (uint) strlen("/.drizzle_history")+2,
1145
 
                                 MYF(MY_WME));
 
1171
      histfile=(char*) malloc(strlen(getenv("HOME")) + strlen("/.drizzle_history") + 2);
1146
1172
      if (histfile)
1147
1173
        sprintf(histfile,"%s/.drizzle_history",getenv("HOME"));
1148
1174
      char link_name[FN_REFLEN];
1150
1176
          strncmp(link_name, "/dev/null", 10) == 0)
1151
1177
      {
1152
1178
        /* The .drizzle_history file is a symlink to /dev/null, don't use it */
1153
 
        my_free(histfile, MYF(MY_ALLOW_ZERO_PTR));
 
1179
        free(histfile);
1154
1180
        histfile= 0;
1155
1181
      }
1156
1182
    }
1159
1185
      if (verbose)
1160
1186
        tee_fprintf(stdout, _("Reading history-file %s\n"),histfile);
1161
1187
      read_history(histfile);
1162
 
      if (!(histfile_tmp= (char*) my_malloc((uint) strlen(histfile) + 5,
1163
 
                                            MYF(MY_WME))))
 
1188
      if (!(histfile_tmp= (char*) malloc((uint) strlen(histfile) + 5)))
1164
1189
      {
1165
1190
        fprintf(stderr, _("Couldn't allocate memory for temp histfile!\n"));
1166
1191
        exit(1);
1180
1205
  return(0);        // Keep compiler happy
1181
1206
}
1182
1207
 
1183
 
sig_handler drizzle_end(int sig)
 
1208
void drizzle_end(int sig)
1184
1209
{
1185
1210
  drizzle_close(&drizzle);
1186
1211
  if (!status.batch && !quick && histfile)
1201
1226
    delete glob_buffer;
1202
1227
  if (processed_prompt)
1203
1228
    delete processed_prompt;
1204
 
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
1205
 
  my_free(opt_drizzle_unix_port,MYF(MY_ALLOW_ZERO_PTR));
1206
 
  my_free(histfile,MYF(MY_ALLOW_ZERO_PTR));
1207
 
  my_free(histfile_tmp,MYF(MY_ALLOW_ZERO_PTR));
1208
 
  my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
1209
 
  my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
1210
 
  my_free(current_user,MYF(MY_ALLOW_ZERO_PTR));
1211
 
  my_free(full_username,MYF(MY_ALLOW_ZERO_PTR));
1212
 
  my_free(part_username,MYF(MY_ALLOW_ZERO_PTR));
1213
 
  my_free(default_prompt,MYF(MY_ALLOW_ZERO_PTR));
1214
 
  my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR));
1215
 
  drizzle_server_end();
 
1229
  free(opt_password);
 
1230
  free(opt_drizzle_unix_port);
 
1231
  free(histfile);
 
1232
  free(histfile_tmp);
 
1233
  free(current_db);
 
1234
  free(current_host);
 
1235
  free(current_user);
 
1236
  free(full_username);
 
1237
  free(part_username);
 
1238
  free(default_prompt);
 
1239
  free(current_prompt);
1216
1240
  free_defaults(defaults_argv);
1217
1241
  my_end(my_end_arg);
1218
1242
  exit(status.exit_status);
1224
1248
  If query is in process, kill query
1225
1249
  no query in process, terminate like previous behavior
1226
1250
*/
1227
 
sig_handler handle_sigint(int sig)
 
1251
extern "C"
 
1252
void handle_sigint(int sig)
1228
1253
{
1229
1254
  char kill_buffer[40];
1230
1255
  DRIZZLE *kill_drizzle= NULL;
1257
1282
 
1258
1283
 
1259
1284
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1260
 
sig_handler window_resize(int sig __attribute__((unused)))
 
1285
void window_resize(int)
1261
1286
{
1262
1287
  struct winsize window_size;
1263
1288
 
1304
1329
  {"database", 'D', N_("Database to use."), (char**) &current_db,
1305
1330
   (char**) &current_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1306
1331
  {"default-character-set", OPT_DEFAULT_CHARSET,
1307
 
   N_("Set the default character set."), (char**) &default_charset,
1308
 
   (char**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1332
   N_("(not used)"), 0,
 
1333
   0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1309
1334
  {"delimiter", OPT_DELIMITER, N_("Delimiter to be used."), (char**) &delimiter_str,
1310
1335
   (char**) &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1311
1336
  {"execute", 'e', N_("Execute command and quit. (Disables --force and history file)"), 0,
1360
1385
  {"no-pager", OPT_NOPAGER,
1361
1386
   N_("Disable pager and print to stdout. See interactive help (\\h) also. WARNING: option deprecated; use --disable-pager instead."),
1362
1387
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1363
 
  {"password", 'p',
 
1388
  {"password", 'P',
1364
1389
   N_("Password to use when connecting to server. If password is not given it's asked from the tty."),
1365
1390
   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, ")
 
1391
  {"port", 'p', N_("Port number to use for connection or 0 for default to, in order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, ")
1367
1392
   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},
 
1393
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1370
1394
  {"prompt", OPT_PROMPT, N_("Set the drizzle prompt to this value."),
1371
1395
   (char**) &current_prompt, (char**) &current_prompt, 0, GET_STR_ALLOC,
1372
1396
   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
1397
  {"quick", 'q',
1376
1398
   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
1399
   (char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1437
1459
  {"show-warnings", OPT_SHOW_WARNINGS, N_("Show warnings after every statement."),
1438
1460
   (char**) &show_warnings, (char**) &show_warnings, 0, GET_BOOL, NO_ARG,
1439
1461
   0, 0, 0, 0, 0, 0},
 
1462
  {"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of lines before each import progress report."),
 
1463
   (char**) &show_progress_size, (char**) &show_progress_size, 0, GET_ULONG, REQUIRED_ARG,
 
1464
   0, 0, 0, 0, 0, 0},
1440
1465
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1441
1466
};
1442
1467
 
1452
1477
 
1453
1478
  if (version)
1454
1479
    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"));
 
1480
  printf(_("Copyright (C) 2008 Sun Microsystems\n"
 
1481
           "This software comes with ABSOLUTELY NO WARRANTY. "
 
1482
           "This is free software,\n"
 
1483
           "and you are welcome to modify and redistribute it "
 
1484
           "under the GPL license\n"));
1459
1485
  printf(_("Usage: %s [OPTIONS] [database]\n"), my_progname);
1460
1486
  my_print_help(my_long_options);
1461
 
  print_defaults("my", load_default_groups);
 
1487
  print_defaults("drizzle", load_default_groups);
1462
1488
  my_print_variables(my_long_options);
1463
1489
}
1464
1490
 
1465
1491
 
1466
 
bool
1467
 
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1468
 
               char *argument)
 
1492
extern "C" bool
 
1493
get_one_option(int optid, const struct my_option *, char *argument)
1469
1494
{
 
1495
  char *endchar= NULL;
 
1496
  uint64_t temp_drizzle_port= 0;
 
1497
 
1470
1498
  switch(optid) {
1471
1499
  case OPT_CHARSETS_DIR:
1472
 
    strmake(drizzle_charsets_dir, argument, sizeof(drizzle_charsets_dir) - 1);
 
1500
    strncpy(drizzle_charsets_dir, argument, sizeof(drizzle_charsets_dir) - 1);
1473
1501
    charsets_dir = drizzle_charsets_dir;
1474
1502
    break;
1475
1503
  case  OPT_DEFAULT_CHARSET:
1478
1506
  case OPT_DELIMITER:
1479
1507
    if (argument == disabled_my_option)
1480
1508
    {
1481
 
      stpcpy(delimiter, DEFAULT_DELIMITER);
 
1509
      strcpy(delimiter, DEFAULT_DELIMITER);
1482
1510
    }
1483
1511
    else
1484
1512
    {
1485
1513
      /* Check that delimiter does not contain a backslash */
1486
1514
      if (!strstr(argument, "\\"))
1487
1515
      {
1488
 
        strmake(delimiter, argument, sizeof(delimiter) - 1);
 
1516
        strncpy(delimiter, argument, sizeof(delimiter) - 1);
1489
1517
      }
1490
1518
      else
1491
1519
      {
1492
1520
        put_info(_("DELIMITER cannot contain a backslash character"),
1493
1521
                 INFO_ERROR,0,0);
1494
 
        return 0;
 
1522
        return false;
1495
1523
      }
1496
1524
    }
1497
1525
    delimiter_length= (uint)strlen(delimiter);
1498
1526
    delimiter_str= delimiter;
1499
1527
    break;
1500
1528
  case OPT_LOCAL_INFILE:
1501
 
    using_opt_local_infile=1;
 
1529
    using_opt_local_infile= 1;
1502
1530
    break;
1503
1531
  case OPT_TEE:
1504
1532
    if (argument == disabled_my_option)
1523
1551
      if (argument && strlen(argument))
1524
1552
      {
1525
1553
        default_pager_set= 1;
1526
 
        strmake(pager, argument, sizeof(pager) - 1);
1527
 
        stpcpy(default_pager, pager);
 
1554
        strncpy(pager, argument, sizeof(pager) - 1);
 
1555
        strcpy(default_pager, pager);
1528
1556
      }
1529
1557
      else if (default_pager_set)
1530
 
        stpcpy(pager, default_pager);
 
1558
        strcpy(pager, default_pager);
1531
1559
      else
1532
1560
        opt_nopager= 1;
1533
1561
    }
1560
1588
      one_database= skip_updates= 1;
1561
1589
    break;
1562
1590
  case 'p':
 
1591
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
 
1592
    /* if there is an alpha character this is not a valid port */
 
1593
    if (strlen(endchar) != 0)
 
1594
    {
 
1595
      put_info(_("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead."), INFO_ERROR, 0, 0);
 
1596
      return false;
 
1597
    }
 
1598
    /* If the port number is > 65535 it is not a valid port
 
1599
       This also helps with potential data loss casting unsigned long to a
 
1600
       uint32_t. */
 
1601
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
 
1602
    {
 
1603
      put_info(_("Value supplied for port is not valid."), INFO_ERROR, 0, 0);
 
1604
      return false;
 
1605
    }
 
1606
    else
 
1607
    {
 
1608
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
 
1609
    }
 
1610
    break;
 
1611
  case 'P':
 
1612
    /* Don't require password */
1563
1613
    if (argument == disabled_my_option)
1564
 
      argument= (char*) "";      // Don't require password
 
1614
    {
 
1615
      argument= (char*) "";
 
1616
    }
1565
1617
    if (argument)
1566
1618
    {
1567
1619
      char *start= argument;
1568
 
      my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
 
1620
      free(opt_password);
1569
1621
      opt_password= strdup(argument);
1570
 
      while (*argument) *argument++= 'x';        // Destroy argument
 
1622
      while (*argument)
 
1623
      {
 
1624
        /* Overwriting password with 'x' */
 
1625
        *argument++= 'x';
 
1626
      }
1571
1627
      if (*start)
1572
 
        start[1]=0 ;
 
1628
      {
 
1629
        start[1]= 0;
 
1630
      }
1573
1631
      tty_password= 0;
1574
1632
    }
1575
1633
    else
 
1634
    {
1576
1635
      tty_password= 1;
 
1636
    }
1577
1637
    break;
1578
1638
  case 's':
1579
1639
    if (argument == disabled_my_option)
1592
1652
    status.add_to_history= 0;
1593
1653
    set_if_bigger(opt_silent,1);                         // more silent
1594
1654
    break;
1595
 
    break;
1596
1655
  case 'V':
1597
1656
    usage(1);
1598
1657
    exit(0);
1618
1677
  pagpoint= getenv("PAGER");
1619
1678
  if (!((char*) (pagpoint)))
1620
1679
  {
1621
 
    stpcpy(pager, "stdout");
 
1680
    strcpy(pager, "stdout");
1622
1681
    opt_nopager= 1;
1623
1682
  }
1624
1683
  else
1625
 
    stpcpy(pager, pagpoint);
1626
 
  stpcpy(default_pager, pager);
 
1684
    strcpy(pager, pagpoint);
 
1685
  strcpy(default_pager, pager);
1627
1686
 
1628
1687
  opt_max_allowed_packet= *drizzle_params->p_max_allowed_packet;
1629
1688
  opt_net_buffer_length= *drizzle_params->p_net_buffer_length;
1636
1695
 
1637
1696
  if (status.batch) /* disable pager and outfile in this case */
1638
1697
  {
1639
 
    stpcpy(default_pager, "stdout");
1640
 
    stpcpy(pager, "stdout");
 
1698
    strcpy(default_pager, "stdout");
 
1699
    strcpy(pager, "stdout");
1641
1700
    opt_nopager= 1;
1642
1701
    default_pager_set= 0;
1643
1702
    opt_outfile= 0;
1645
1704
    connect_flag= 0; /* Not in interactive mode */
1646
1705
  }
1647
1706
 
1648
 
  if (strcmp(default_charset, charset_info->csname) &&
1649
 
      !(charset_info= get_charset_by_csname(default_charset,
1650
 
                                            MY_CS_PRIMARY, MYF(MY_WME))))
1651
 
    exit(1);
1652
1707
  if (argc > 1)
1653
1708
  {
1654
1709
    usage(0);
1657
1712
  if (argc == 1)
1658
1713
  {
1659
1714
    skip_updates= 0;
1660
 
    my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
 
1715
    free(current_db);
1661
1716
    current_db= strdup(*argv);
1662
1717
  }
1663
1718
  if (tty_password)
1664
 
    opt_password= get_tty_password(NullS);
 
1719
    opt_password= get_tty_password(NULL);
1665
1720
  if (debug_info_flag)
1666
1721
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
1667
1722
  if (debug_check_flag)
1690
1745
        you save the file using "Unicode UTF-8" format.
1691
1746
      */
1692
1747
      if (!line_number &&
1693
 
          (uchar) line[0] == 0xEF &&
1694
 
          (uchar) line[1] == 0xBB &&
1695
 
          (uchar) line[2] == 0xBF)
 
1748
          (unsigned char) line[0] == 0xEF &&
 
1749
          (unsigned char) line[1] == 0xBB &&
 
1750
          (unsigned char) line[2] == 0xBF)
1696
1751
        line+= 3;
1697
1752
      line_number++;
 
1753
      if (show_progress_size > 0)
 
1754
      {
 
1755
        if ((line_number % show_progress_size) == 0)
 
1756
          fprintf(stderr, _("Processing line: %"PRIu32"\n"), line_number);
 
1757
      }
1698
1758
      if (!glob_buffer->empty())
1699
1759
        status.query_start_line=line_number;
1700
1760
    }
1786
1846
    if (strstr(name, "\\g") || (strstr(name, delimiter) &&
1787
1847
                                !(strlen(name) >= 9 &&
1788
1848
                                  !my_strnncoll(charset_info,
1789
 
                                                (uchar*) name, 9,
1790
 
                                                (const uchar*) "delimiter",
 
1849
                                                (unsigned char*) name, 9,
 
1850
                                                (const unsigned char*) "delimiter",
1791
1851
                                                9))))
1792
1852
      return((COMMANDS *) 0);
1793
1853
    if ((end=strcont(name," \t")))
1805
1865
  for (uint i= 0; commands[i].name; i++)
1806
1866
  {
1807
1867
    if (commands[i].func &&
1808
 
        ((name && !my_strnncoll(charset_info,(const uchar*)name,len, (const uchar*)commands[i].name,len) && !commands[i].name[len] && (!end || (end && commands[i].takes_params))) || (!name && commands[i].cmd_char == cmd_char)))
 
1868
        ((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)))
1809
1869
    {
1810
1870
      return(&commands[i]);
1811
1871
    }
1817
1877
static bool add_line(string *buffer, char *line, char *in_string,
1818
1878
                        bool *ml_comment)
1819
1879
{
1820
 
  uchar inchar;
 
1880
  unsigned char inchar;
1821
1881
  char buff[80], *pos, *out;
1822
1882
  COMMANDS *com;
1823
1883
  bool need_space= 0;
1830
1890
    add_history(line);
1831
1891
  char *end_of_line=line+(uint) strlen(line);
1832
1892
 
1833
 
  for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
 
1893
  for (pos=out=line ; (inchar= (unsigned char) *pos) ; pos++)
1834
1894
  {
1835
1895
    if (!preserve_comments)
1836
1896
    {
1862
1922
    {
1863
1923
      // Found possbile one character command like \c
1864
1924
 
1865
 
      if (!(inchar = (uchar) *++pos))
 
1925
      if (!(inchar = (unsigned char) *++pos))
1866
1926
        break;        // readline adds one '\'
1867
1927
      if (*in_string || inchar == 'N')  // \N is short for NULL
1868
1928
      {          // Don't allow commands in string
1870
1930
        *out++= (char) inchar;
1871
1931
        continue;
1872
1932
      }
1873
 
      if ((com=find_command(NullS,(char) inchar)))
 
1933
      if ((com=find_command(NULL,(char) inchar)))
1874
1934
      {
1875
1935
        // Flush previously accepted characters
1876
1936
        if (out != line)
1919
1979
    }
1920
1980
    else if (!*ml_comment && !*in_string &&
1921
1981
             (end_of_line - pos) >= 10 &&
1922
 
             !my_strnncoll(charset_info, (uchar*) pos, 10,
1923
 
                           (const uchar*) "delimiter ", 10))
 
1982
             !my_strnncoll(charset_info, (unsigned char*) pos, 10,
 
1983
                           (const unsigned char*) "delimiter ", 10))
1924
1984
    {
1925
1985
      // Flush previously accepted characters
1926
1986
      if (out != line)
2085
2145
 
2086
2146
 
2087
2147
static char **mysql_completion (const char *text, int start, int end);
2088
 
static char *new_command_generator(const char *text, int);
 
2148
extern "C" char *new_command_generator(const char *text, int);
2089
2149
 
2090
2150
/*
2091
2151
  Tell the GNU Readline library how to complete.  We want to try to complete
2092
2152
  on command names if this is the first word in the line, or on filenames
2093
2153
  if not.
2094
2154
*/
2095
 
static char *no_completion(const char * a __attribute__((unused)),
2096
 
                           int b __attribute__((unused)))
 
2155
static char *no_completion(const char *, int)
2097
2156
{
2098
2157
  /* No filename completion */
2099
2158
  return 0;
2188
2247
  entire line in case we want to do some simple parsing.  Return the
2189
2248
  array of matches, or NULL if there aren't any.
2190
2249
*/
2191
 
char **mysql_completion (const char *text,
2192
 
                        int start __attribute__((unused)),
2193
 
                        int end __attribute__((unused)))
 
2250
char **mysql_completion (const char *text, int, int)
2194
2251
{
2195
2252
  if (!status.batch && !quick)
2196
2253
    return rl_completion_matches(text, new_command_generator);
2198
2255
    return (char**) 0;
2199
2256
}
2200
2257
 
2201
 
 
2202
 
static char *new_command_generator(const char *text,int state)
 
2258
extern "C"
 
2259
char *new_command_generator(const char *text,int state)
2203
2260
{
2204
2261
  static int textlen;
2205
2262
  char *ptr;
2218
2275
 
2219
2276
      b = find_all_matches(&ht,text,(uint) strlen(text),&len);
2220
2277
      if (!b)
2221
 
        return NullS;
 
2278
        return NULL;
2222
2279
      e = b->pData;
2223
2280
    }
2224
2281
 
2245
2302
        }
2246
2303
      }
2247
2304
    }
2248
 
    ptr= NullS;
 
2305
    ptr= NULL;
2249
2306
    while (e && !ptr)
2250
2307
    {          /* find valid entry in bucket */
2251
2308
      if ((uint) strlen(e->str) == b->nKeyLength)
2274
2331
    if (ptr)
2275
2332
      return ptr;
2276
2333
  }
2277
 
  return NullS;
 
2334
  return NULL;
2278
2335
}
2279
2336
 
2280
2337
 
2365
2422
  i=0;
2366
2423
  while ((table_row=drizzle_fetch_row(tables)))
2367
2424
  {
2368
 
    if ((fields=drizzle_list_fields(&drizzle,(const char*) table_row[0],NullS)))
 
2425
    if ((fields=drizzle_list_fields(&drizzle,(const char*) table_row[0],NULL)))
2369
2426
    {
2370
2427
      num_fields=drizzle_num_fields(fields);
2371
2428
      if (!(field_names[i] = (char **) alloc_root(&hash_mem_root,
2412
2469
    for (;;)
2413
2470
    {
2414
2471
      if (*s == (char) c) return (char*) s;
2415
 
      if (!*s++) return NullS;
 
2472
      if (!*s++) return NULL;
2416
2473
    }
2417
2474
  }
2418
2475
 
2420
2477
  {
2421
2478
    register char *t;
2422
2479
 
2423
 
    t = NullS;
 
2480
    t = NULL;
2424
2481
    do if (*s == (char) c) t = (char*) s; while (*s++);
2425
2482
    return (char*) t;
2426
2483
  }
2448
2505
{
2449
2506
  DRIZZLE_RES *res;
2450
2507
 
2451
 
  my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
 
2508
  free(current_db);
2452
2509
  current_db= NULL;
2453
2510
  /* In case of error below current_db will be NULL */
2454
2511
  if (!drizzle_query(&drizzle, "SELECT DATABASE()") &&
2503
2560
}
2504
2561
 
2505
2562
 
2506
 
static int com_server_help(string *buffer,
2507
 
                           const char *line __attribute__((unused)),
2508
 
                           char *help_arg)
 
2563
static int com_server_help(string *buffer, const char *, const char *help_arg)
2509
2564
{
2510
2565
  DRIZZLE_ROW cur;
2511
2566
  const char *server_cmd= buffer->c_str();
2512
 
  char cmd_buf[100];
 
2567
  string cmd_buf;
2513
2568
  DRIZZLE_RES *result;
2514
2569
  int error;
2515
2570
 
 
2571
  cmd_buf.reserve(100);
2516
2572
  if (help_arg[0] != '\'')
2517
2573
  {
2518
 
    char *end_arg= strend(help_arg);
 
2574
    const char *end_arg= strchr(help_arg, '\0');
2519
2575
    if(--end_arg)
2520
2576
    {
2521
2577
      while (my_isspace(charset_info,*end_arg))
2522
2578
        end_arg--;
2523
 
      *++end_arg= '\0';
2524
2579
    }
2525
 
    (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
2526
 
    server_cmd= cmd_buf;
 
2580
    cmd_buf.append("help '");
 
2581
    cmd_buf.append(help_arg, end_arg-help_arg);
 
2582
    cmd_buf.append("'");
 
2583
 
 
2584
    server_cmd= cmd_buf.c_str();
2527
2585
  }
2528
2586
 
2529
2587
  if (!connected && reconnect())
2595
2653
}
2596
2654
 
2597
2655
static int
2598
 
com_help(string *buffer __attribute__((unused)),
2599
 
         const char *line __attribute__((unused)))
 
2656
com_help(string *buffer, const char *line)
2600
2657
{
2601
2658
  register int i, j;
2602
 
  char * help_arg= strchr(line,' '), buff[32], *end;
 
2659
  const char *help_arg= strchr(line,' ');
 
2660
  char buff[32], *end;
2603
2661
  if (help_arg)
2604
2662
  {
2605
2663
    while (my_isspace(charset_info,*help_arg))
2612
2670
    put_info(_("Note that all text commands must be first on line and end with ';'"),INFO_INFO,0,0);
2613
2671
  for (i = 0; commands[i].name; i++)
2614
2672
  {
2615
 
    end= stpcpy(buff, commands[i].name);
 
2673
    end= strcpy(buff, commands[i].name);
 
2674
    end+= strlen(commands[i].name);
2616
2675
    for (j= (int)strlen(commands[i].name); j < 10; j++)
2617
 
      end= stpcpy(end, " ");
 
2676
      end= strcpy(end, " ")+1;
2618
2677
    if (commands[i].func)
2619
2678
      tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
2620
2679
                  commands[i].cmd_char, _(commands[i].doc));
2626
2685
 
2627
2686
 
2628
2687
static int
2629
 
com_clear(string *buffer,
2630
 
          const char *line __attribute__((unused)))
 
2688
com_clear(string *buffer, const char *)
2631
2689
{
2632
2690
  if (status.add_to_history)
2633
2691
    fix_history(buffer);
2635
2693
  return 0;
2636
2694
}
2637
2695
 
2638
 
static int
2639
 
com_charset(string *buffer __attribute__((unused)),
2640
 
            const char *line)
2641
 
{
2642
 
  char buff[256], *param;
2643
 
  const CHARSET_INFO * new_cs;
2644
 
  strmake(buff, line, sizeof(buff) - 1);
2645
 
  param= get_arg(buff, 0);
2646
 
  if (!param || !*param)
2647
 
  {
2648
 
    return put_info(_("Usage: \\C char_setname | charset charset_name"),
2649
 
                    INFO_ERROR, 0, 0);
2650
 
  }
2651
 
  new_cs= get_charset_by_csname(param, MY_CS_PRIMARY, MYF(MY_WME));
2652
 
  if (new_cs)
2653
 
  {
2654
 
    charset_info= new_cs;
2655
 
    drizzle_set_character_set(&drizzle, charset_info->csname);
2656
 
    default_charset= (char *)charset_info->csname;
2657
 
    default_charset_used= 1;
2658
 
    put_info(_("Charset changed"), INFO_INFO,0,0);
2659
 
  }
2660
 
  else put_info(_("Charset is not found"), INFO_INFO,0,0);
2661
 
  return 0;
2662
 
}
2663
2696
 
2664
2697
/*
2665
2698
  Execute command
2668
2701
  1  if fatal error
2669
2702
*/
2670
2703
static int
2671
 
com_go(string *buffer,
2672
 
       const char *line __attribute__((unused)))
 
2704
com_go(string *buffer, const char *)
2673
2705
{
2674
2706
  char          buff[200]; /* about 110 chars used so far */
2675
2707
  char          time_buff[52+3+1]; /* time max + space&parens + NUL */
2752
2784
    {
2753
2785
      if (!drizzle_num_rows(result) && ! quick && !column_types_flag)
2754
2786
      {
2755
 
        stpcpy(buff, _("Empty set"));
 
2787
        strcpy(buff, _("Empty set"));
2756
2788
      }
2757
2789
      else
2758
2790
      {
2774
2806
      }
2775
2807
    }
2776
2808
    else if (drizzle_affected_rows(&drizzle) == ~(uint64_t) 0)
2777
 
      stpcpy(buff,_("Query OK"));
 
2809
      strcpy(buff,_("Query OK"));
2778
2810
    else
2779
2811
      sprintf(buff, ngettext("Query OK, %ld row affected",
2780
2812
                             "Query OK, %ld rows affected",
2781
2813
                             (long) drizzle_affected_rows(&drizzle)),
2782
2814
              (long) drizzle_affected_rows(&drizzle));
2783
2815
 
2784
 
    pos=strend(buff);
 
2816
    pos= strchr(buff, '\0');
2785
2817
    if ((warnings= drizzle_warning_count(&drizzle)))
2786
2818
    {
2787
2819
      *pos++= ',';
2788
2820
      *pos++= ' ';
2789
 
      pos=int10_to_str(warnings, pos, 10);
2790
 
      pos=stpcpy(pos, " warning");
 
2821
      pos= int10_to_str(warnings, pos, 10);
 
2822
      pos= strcpy(pos, " warning")+8;
2791
2823
      if (warnings != 1)
2792
2824
        *pos++= 's';
2793
2825
    }
2794
 
    stpcpy(pos, time_buff);
 
2826
    strcpy(pos, time_buff);
2795
2827
    put_info(buff,INFO_RESULT,0,0);
2796
2828
    if (drizzle_info(&drizzle))
2797
2829
      put_info(drizzle_info(&drizzle),INFO_RESULT,0,0);
2853
2885
    return;
2854
2886
  }
2855
2887
  OUTFILE = new_outfile;
2856
 
  strmake(outfile, file_name, FN_REFLEN-1);
 
2888
  strncpy(outfile, file_name, FN_REFLEN-1);
2857
2889
  tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
2858
2890
  opt_outfile= 1;
2859
2891
  return;
2885
2917
{
2886
2918
  switch (type) {
2887
2919
    case DRIZZLE_TYPE_BLOB:        return "BLOB";
2888
 
    case DRIZZLE_TYPE_NEWDATE:        return "DATE";
 
2920
    case DRIZZLE_TYPE_DATE:        return "DATE";
2889
2921
    case DRIZZLE_TYPE_DATETIME:    return "DATETIME";
2890
2922
    case DRIZZLE_TYPE_NEWDECIMAL:  return "DECIMAL";
2891
2923
    case DRIZZLE_TYPE_DOUBLE:      return "DOUBLE";
2893
2925
    case DRIZZLE_TYPE_LONG:        return "LONG";
2894
2926
    case DRIZZLE_TYPE_LONGLONG:    return "LONGLONG";
2895
2927
    case DRIZZLE_TYPE_NULL:        return "NULL";
2896
 
    case DRIZZLE_TYPE_SHORT:       return "SHORT";
2897
2928
    case DRIZZLE_TYPE_TIME:        return "TIME";
2898
2929
    case DRIZZLE_TYPE_TIMESTAMP:   return "TIMESTAMP";
2899
2930
    case DRIZZLE_TYPE_TINY:        return "TINY";
 
2931
    case DRIZZLE_TYPE_VIRTUAL:     return "VIRTUAL";
2900
2932
    default:                     return "?-unknown-?";
2901
2933
  }
2902
2934
}
2906
2938
  char *s=buf;
2907
2939
  *s=0;
2908
2940
#define ff2s_check_flag(X)                                              \
2909
 
  if (f & X ## _FLAG) { s=stpcpy(s, # X " "); f &= ~ X ## _FLAG; }
 
2941
  if (f & X ## _FLAG) { s=strcpy(s, # X " ")+strlen(# X " "); \
 
2942
                        f &= ~ X ## _FLAG; }
2910
2943
  ff2s_check_flag(NOT_NULL);
2911
2944
  ff2s_check_flag(PRI_KEY);
2912
2945
  ff2s_check_flag(UNIQUE_KEY);
2968
3001
  DRIZZLE_FIELD   *field;
2969
3002
  bool          *num_flag;
2970
3003
  string separator;
2971
 
  
 
3004
 
2972
3005
  separator.reserve(256);
2973
3006
 
2974
 
  num_flag=(bool*) my_malloc(sizeof(bool)*drizzle_num_fields(result),
2975
 
                             MYF(MY_WME));
 
3007
  num_flag=(bool*) malloc(sizeof(bool)*drizzle_num_fields(result));
2976
3008
  if (column_types_flag)
2977
3009
  {
2978
3010
    print_field_types(result);
2988
3020
      length=max(length,field->length);
2989
3021
    else
2990
3022
      length=max(length,field->max_length);
2991
 
    if (length < 4 && !IS_NOT_NULL(field->flags))
 
3023
    if (length < 4 && !(field->flags & NOT_NULL_FLAG))
2992
3024
      // Room for "NULL"
2993
3025
      length=4;
2994
3026
    field->max_length=length;
3013
3045
      tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
3014
3046
                                             MAX_COLUMN_LENGTH),
3015
3047
                  field->name);
3016
 
      num_flag[off]= IS_NUM(field->type);
 
3048
      num_flag[off]= ((field->type <= DRIZZLE_TYPE_LONGLONG) ||
 
3049
                      (field->type == DRIZZLE_TYPE_NEWDECIMAL));
3017
3050
    }
3018
3051
    (void) tee_fputs("\n", PAGER);
3019
3052
    tee_puts((char*) separator.c_str(), PAGER);
3074
3107
    (void) tee_fputs("\n", PAGER);
3075
3108
  }
3076
3109
  tee_puts(separator.c_str(), PAGER);
3077
 
  my_free(num_flag, MYF(MY_ALLOW_ZERO_PTR));
 
3110
  free(num_flag);
3078
3111
}
3079
3112
 
3080
3113
/**
3095
3128
*/
3096
3129
static int get_field_disp_length(DRIZZLE_FIELD *field)
3097
3130
{
3098
 
  uint length= column_names ? field->name_length : 0;
 
3131
  uint32_t length= column_names ? field->name_length : 0;
3099
3132
 
3100
3133
  if (quick)
3101
3134
    length= max(length, field->length);
3102
3135
  else
3103
3136
    length= max(length, field->max_length);
3104
3137
 
3105
 
  if (length < 4 && !IS_NOT_NULL(field->flags))
 
3138
  if (length < 4 && !(field->flags & NOT_NULL_FLAG))
3106
3139
    length= 4;        /* Room for "NULL" */
3107
3140
 
3108
3141
  return length;
3204
3237
  DRIZZLE_RES    *result;
3205
3238
  DRIZZLE_ROW    cur;
3206
3239
  uint64_t num_rows;
3207
 
 
 
3240
 
3208
3241
  /* Save current error before calling "show warnings" */
3209
3242
  uint error= drizzle_errno(&drizzle);
3210
3243
 
3310
3343
}
3311
3344
 
3312
3345
static int
3313
 
com_tee(string *buffer __attribute__((unused)), const char *line )
 
3346
com_tee(string *, const char *line )
3314
3347
{
3315
 
  char file_name[FN_REFLEN], *end, *param;
 
3348
  char file_name[FN_REFLEN], *end;
 
3349
  const char *param;
3316
3350
 
3317
3351
  if (status.batch)
3318
3352
    return 0;
3337
3371
  /* eliminate the spaces before the parameters */
3338
3372
  while (my_isspace(charset_info,*param))
3339
3373
    param++;
3340
 
  end= strmake(file_name, param, sizeof(file_name) - 1);
 
3374
  strncpy(file_name, param, sizeof(file_name) - 1);
 
3375
  end= file_name + strlen(file_name);
3341
3376
  /* remove end space from command line */
3342
3377
  while (end > file_name && (my_isspace(charset_info,end[-1]) ||
3343
3378
                             my_iscntrl(charset_info,end[-1])))
3354
3389
 
3355
3390
 
3356
3391
static int
3357
 
com_notee(string *buffer __attribute__((unused)),
3358
 
          const char *line __attribute__((unused)))
 
3392
com_notee(string *, const char *)
3359
3393
{
3360
3394
  if (opt_outfile)
3361
3395
    end_tee();
3368
3402
*/
3369
3403
 
3370
3404
static int
3371
 
com_pager(string *buffer __attribute__((unused)),
3372
 
          const char *line __attribute__((unused)))
 
3405
com_pager(string *, const char *line)
3373
3406
{
3374
 
  char pager_name[FN_REFLEN], *end, *param;
 
3407
  char pager_name[FN_REFLEN], *end;
 
3408
  const char *param;
3375
3409
 
3376
3410
  if (status.batch)
3377
3411
    return 0;
3389
3423
    {
3390
3424
      tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
3391
3425
      opt_nopager=1;
3392
 
      stpcpy(pager, "stdout");
 
3426
      strcpy(pager, "stdout");
3393
3427
      PAGER= stdout;
3394
3428
      return 0;
3395
3429
    }
3396
 
    stpcpy(pager, default_pager);
 
3430
    strcpy(pager, default_pager);
3397
3431
  }
3398
3432
  else
3399
3433
  {
3400
 
    end= strmake(pager_name, param, sizeof(pager_name)-1);
 
3434
    end= strncpy(pager_name, param, sizeof(pager_name)-1);
 
3435
    end+= strlen(pager_name);
3401
3436
    while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
3402
3437
                                my_iscntrl(charset_info,end[-1])))
3403
3438
      end--;
3404
3439
    end[0]=0;
3405
 
    stpcpy(pager, pager_name);
3406
 
    stpcpy(default_pager, pager_name);
 
3440
    strcpy(pager, pager_name);
 
3441
    strcpy(default_pager, pager_name);
3407
3442
  }
3408
3443
  opt_nopager=0;
3409
3444
  tee_fprintf(stdout, "PAGER set to '%s'\n", pager);
3412
3447
 
3413
3448
 
3414
3449
static int
3415
 
com_nopager(string *buffer __attribute__((unused)),
3416
 
            const char *line __attribute__((unused)))
 
3450
com_nopager(string *, const char *)
3417
3451
{
3418
 
  stpcpy(pager, "stdout");
 
3452
  strcpy(pager, "stdout");
3419
3453
  opt_nopager=1;
3420
3454
  PAGER= stdout;
3421
3455
  tee_fprintf(stdout, "PAGER set to stdout\n");
3425
3459
/* If arg is given, exit without errors. This happens on command 'quit' */
3426
3460
 
3427
3461
static int
3428
 
com_quit(string *buffer __attribute__((unused)),
3429
 
         const char *line __attribute__((unused)))
 
3462
com_quit(string *, const char *)
3430
3463
{
3431
3464
  /* let the screen auto close on a normal shutdown */
3432
3465
  status.exit_status=0;
3434
3467
}
3435
3468
 
3436
3469
static int
3437
 
com_rehash(string *buffer __attribute__((unused)),
3438
 
           const char *line __attribute__((unused)))
 
3470
com_rehash(string *, const char *)
3439
3471
{
3440
3472
  build_completion_hash(1, 0);
3441
3473
  return 0;
3444
3476
 
3445
3477
 
3446
3478
static int
3447
 
com_print(string *buffer,const char *line __attribute__((unused)))
 
3479
com_print(string *buffer,const char *)
3448
3480
{
3449
3481
  tee_puts("--------------", stdout);
3450
3482
  (void) tee_fputs(buffer->c_str(), stdout);
3471
3503
      Two null bytes are needed in the end of buff to allow
3472
3504
      get_arg to find end of string the second time it's called.
3473
3505
    */
3474
 
    tmp= strmake(buff, line, sizeof(buff)-2);
 
3506
    tmp= strncpy(buff, line, sizeof(buff)-2);
3475
3507
#ifdef EXTRA_DEBUG
3476
3508
    tmp[1]= 0;
3477
3509
#endif
3478
3510
    tmp= get_arg(buff, 0);
3479
3511
    if (tmp && *tmp)
3480
3512
    {
3481
 
      my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
 
3513
      free(current_db);
3482
3514
      current_db= strdup(tmp);
3483
3515
      tmp= get_arg(buff, 1);
3484
3516
      if (tmp)
3485
3517
      {
3486
 
        my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
 
3518
        free(current_host);
3487
3519
        current_host=strdup(tmp);
3488
3520
      }
3489
3521
    }
3513
3545
}
3514
3546
 
3515
3547
 
3516
 
static int com_source(string *buffer __attribute__((unused)), const char *line)
 
3548
static int com_source(string *, const char *line)
3517
3549
{
3518
 
  char source_name[FN_REFLEN], *end, *param;
 
3550
  char source_name[FN_REFLEN], *end;
 
3551
  const char *param;
3519
3552
  LINE_BUFFER *line_buff;
3520
3553
  int error;
3521
3554
  STATUS old_status;
3529
3562
                    INFO_ERROR, 0,0);
3530
3563
  while (my_isspace(charset_info,*param))
3531
3564
    param++;
3532
 
  end=strmake(source_name,param,sizeof(source_name)-1);
 
3565
  end= strncpy(source_name,param,sizeof(source_name)-1);
 
3566
  end+= strlen(source_name);
3533
3567
  while (end > source_name && (my_isspace(charset_info,end[-1]) ||
3534
3568
                               my_iscntrl(charset_info,end[-1])))
3535
3569
    end--;
3536
3570
  end[0]=0;
3537
3571
  unpack_filename(source_name,source_name);
3538
3572
  /* open file name */
3539
 
  if (!(sql_file = my_fopen(source_name, O_RDONLY | O_BINARY,MYF(0))))
 
3573
  if (!(sql_file = my_fopen(source_name, O_RDONLY,MYF(0))))
3540
3574
  {
3541
3575
    char buff[FN_REFLEN+60];
3542
3576
    sprintf(buff,"Failed to open file '%s', error: %d", source_name,errno);
3571
3605
 
3572
3606
/* ARGSUSED */
3573
3607
static int
3574
 
com_delimiter(string *buffer __attribute__((unused)), const char *line)
 
3608
com_delimiter(string *, const char *line)
3575
3609
{
3576
3610
  char buff[256], *tmp;
3577
3611
 
3578
 
  strmake(buff, line, sizeof(buff) - 1);
 
3612
  strncpy(buff, line, sizeof(buff) - 1);
3579
3613
  tmp= get_arg(buff, 0);
3580
3614
 
3581
3615
  if (!tmp || !*tmp)
3593
3627
      return 0;
3594
3628
    }
3595
3629
  }
3596
 
  strmake(delimiter, tmp, sizeof(delimiter) - 1);
 
3630
  strncpy(delimiter, tmp, sizeof(delimiter) - 1);
3597
3631
  delimiter_length= (int)strlen(delimiter);
3598
3632
  delimiter_str= delimiter;
3599
3633
  return 0;
3601
3635
 
3602
3636
/* ARGSUSED */
3603
3637
static int
3604
 
com_use(string *buffer __attribute__((unused)), const char *line)
 
3638
com_use(string *, const char *line)
3605
3639
{
3606
3640
  char *tmp, buff[FN_REFLEN + 1];
3607
3641
  int select_db;
3608
3642
 
3609
3643
  memset(buff, 0, sizeof(buff));
3610
 
  strmake(buff, line, sizeof(buff) - 1);
 
3644
  strncpy(buff, line, sizeof(buff) - 1);
3611
3645
  tmp= get_arg(buff, 0);
3612
3646
  if (!tmp || !*tmp)
3613
3647
  {
3662
3696
      if (drizzle_select_db(&drizzle,tmp))
3663
3697
        return put_error(&drizzle);
3664
3698
    }
3665
 
    my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
 
3699
    free(current_db);
3666
3700
    current_db= strdup(tmp);
3667
3701
    if (select_db > 1)
3668
3702
      build_completion_hash(opt_rehash, 1);
3673
3707
}
3674
3708
 
3675
3709
static int
3676
 
com_warnings(string *buffer __attribute__((unused)),
3677
 
             const char *line __attribute__((unused)))
 
3710
com_warnings(string *, const char *)
3678
3711
{
3679
3712
  show_warnings = 1;
3680
3713
  put_info("Show warnings enabled.",INFO_INFO, 0, 0);
3682
3715
}
3683
3716
 
3684
3717
static int
3685
 
com_nowarnings(string *buffer __attribute__((unused)),
3686
 
               const char *line __attribute__((unused)))
 
3718
com_nowarnings(string *, const char *)
3687
3719
{
3688
3720
  show_warnings = 0;
3689
3721
  put_info("Show warnings disabled.",INFO_INFO, 0, 0);
3725
3757
        ptr++;
3726
3758
  }
3727
3759
  if (!*ptr)
3728
 
    return NullS;
 
3760
    return NULL;
3729
3761
  while (my_isspace(charset_info, *ptr))
3730
3762
    ptr++;
3731
3763
  if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
3739
3771
    if (*ptr == '\\' && ptr[1]) // escaped character
3740
3772
    {
3741
3773
      // Remove the backslash
3742
 
      stpcpy(ptr, ptr+1);
 
3774
      strcpy(ptr, ptr+1);
3743
3775
    }
3744
3776
    else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
3745
3777
    {
3748
3780
    }
3749
3781
  }
3750
3782
  valid_arg= ptr != start;
3751
 
  return valid_arg ? start : NullS;
 
3783
  return valid_arg ? start : NULL;
3752
3784
}
3753
3785
 
3754
3786
 
3769
3801
                  (char*) &timeout);
3770
3802
  }
3771
3803
  if (opt_compress)
3772
 
    drizzle_options(&drizzle,DRIZZLE_OPT_COMPRESS,NullS);
 
3804
    drizzle_options(&drizzle,DRIZZLE_OPT_COMPRESS,NULL);
3773
3805
  if (opt_secure_auth)
3774
3806
    drizzle_options(&drizzle, DRIZZLE_SECURE_AUTH, (char *) &opt_secure_auth);
3775
3807
  if (using_opt_local_infile)
3776
3808
    drizzle_options(&drizzle,DRIZZLE_OPT_LOCAL_INFILE, (char*) &opt_local_infile);
3777
 
  drizzle_options(&drizzle,DRIZZLE_OPT_PROTOCOL,(char*)&opt_protocol);
3778
3809
  if (safe_updates)
3779
3810
  {
3780
3811
    char init_command[100];
3781
3812
    sprintf(init_command,
3782
3813
            "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%"PRIu32
3783
 
            ",SQL_MAX_JOIN_SIZE=%"PRIu32,
 
3814
            ",MAX_JOIN_SIZE=%"PRIu32,
3784
3815
            select_limit, max_join_size);
3785
3816
    drizzle_options(&drizzle, DRIZZLE_INIT_COMMAND, init_command);
3786
3817
  }
3787
 
  if (default_charset_used)
3788
 
    drizzle_options(&drizzle, DRIZZLE_SET_CHARSET_NAME, default_charset);
3789
3818
  if (!drizzle_connect(&drizzle, host, user, password,
3790
3819
                          database, opt_drizzle_port, opt_drizzle_unix_port,
3791
3820
                          connect_flag | CLIENT_MULTI_STATEMENTS))
3808
3837
 
3809
3838
 
3810
3839
static int
3811
 
com_status(string *buffer __attribute__((unused)),
3812
 
           const char *line __attribute__((unused)))
 
3840
com_status(string *, const char *)
3813
3841
{
3814
3842
  char buff[40];
3815
3843
  uint64_t id;
3873
3901
    }
3874
3902
    drizzle_free_result(result);
3875
3903
  }
3876
 
  else
3877
 
  {
3878
 
    /* Probably pre-4.1 server */
3879
 
    tee_fprintf(stdout, "Client characterset:\t%s\n", charset_info->csname);
3880
 
    tee_fprintf(stdout, "Server characterset:\t%s\n", drizzle.charset->csname);
3881
 
  }
3882
3904
 
3883
3905
  if (strstr(drizzle_get_host_info(&drizzle),"TCP/IP") || ! drizzle.unix_socket)
3884
3906
    tee_fprintf(stdout, "TCP port:\t\t%d\n", drizzle.port);
3906
3928
static const char *
3907
3929
server_version_string(DRIZZLE *con)
3908
3930
{
3909
 
  static char buf[MAX_SERVER_VERSION_LENGTH] = "";
 
3931
  static string buf("");
 
3932
  static bool server_version_string_reserved= false;
3910
3933
 
 
3934
  if (!server_version_string_reserved)
 
3935
  {
 
3936
    buf.reserve(MAX_SERVER_VERSION_LENGTH);
 
3937
    server_version_string_reserved= true;
 
3938
  }
3911
3939
  /* Only one thread calls this, so no synchronization is needed */
3912
3940
  if (buf[0] == '\0')
3913
3941
  {
3914
 
    char *bufp = buf;
3915
3942
    DRIZZLE_RES *result;
3916
3943
 
3917
 
    bufp= stpncpy(buf, drizzle_get_server_info(con), sizeof buf);
 
3944
    buf.append(drizzle_get_server_info(con));
3918
3945
 
3919
3946
    /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */
3920
3947
    if (!drizzle_query(con, "select @@version_comment limit 1") &&
3923
3950
      DRIZZLE_ROW cur = drizzle_fetch_row(result);
3924
3951
      if (cur && cur[0])
3925
3952
      {
3926
 
        bufp = strxnmov(bufp, sizeof buf - (bufp - buf), " ", cur[0], NullS);
 
3953
        buf.append(" ");
 
3954
        buf.append(cur[0]);
3927
3955
      }
3928
3956
      drizzle_free_result(result);
3929
3957
    }
3930
 
 
3931
 
    /* str*nmov doesn't guarantee NUL-termination */
3932
 
    if (bufp == buf + sizeof buf)
3933
 
      buf[sizeof buf - 1] = '\0';
3934
3958
  }
3935
3959
 
3936
 
  return buf;
 
3960
  return buf.c_str();
3937
3961
}
3938
3962
 
3939
3963
static int
4096
4120
  if (sec >= 3600.0*24)
4097
4121
  {
4098
4122
    tmp=(uint32_t) floor(sec/(3600.0*24));
4099
 
    sec-=3600.0*24*tmp;
4100
 
    buff=int10_to_str((long) tmp, buff, 10);
4101
 
    buff=stpcpy(buff,tmp > 1 ? " days " : " day ");
 
4123
    sec-= 3600.0*24*tmp;
 
4124
    buff= int10_to_str((long) tmp, buff, 10);
 
4125
 
 
4126
    if (tmp > 1)
 
4127
      buff= strcpy(buff," days ")+6;
 
4128
    else
 
4129
      buff= strcpy(buff," day ")+5;
 
4130
 
4102
4131
  }
4103
4132
  if (sec >= 3600.0)
4104
4133
  {
4105
4134
    tmp=(uint32_t) floor(sec/3600.0);
4106
4135
    sec-=3600.0*tmp;
4107
4136
    buff=int10_to_str((long) tmp, buff, 10);
4108
 
    buff=stpcpy(buff,tmp > 1 ? " hours " : " hour ");
 
4137
 
 
4138
    if (tmp > 1)
 
4139
      buff= strcpy(buff, " hours ")+7;
 
4140
    else
 
4141
      buff= strcpy(buff, " hour ")+6;
4109
4142
  }
4110
4143
  if (sec >= 60.0)
4111
4144
  {
4112
4145
    tmp=(uint32_t) floor(sec/60.0);
4113
4146
    sec-=60.0*tmp;
4114
4147
    buff=int10_to_str((long) tmp, buff, 10);
4115
 
    buff=stpcpy(buff," min ");
 
4148
    buff= strcpy(buff," min ")+5;
4116
4149
  }
4117
4150
  if (part_second)
4118
4151
    sprintf(buff,"%.2f sec",sec);
4133
4166
  buff[0]=' ';
4134
4167
  buff[1]='(';
4135
4168
  end_timer(start_time,buff+2);
4136
 
  stpcpy(strend(buff),")");
 
4169
  strcpy(strchr(buff, '\0'),")");
4137
4170
}
4138
4171
 
4139
4172
static const char * construct_prompt()
4226
4259
        break;
4227
4260
      case PROMPT_CHAR:
4228
4261
        {
4229
 
          char c= PROMPT_CHAR;
4230
 
          processed_prompt->append(&c, 1);
 
4262
          processed_prompt->append(PROMPT_CHAR, 1);
4231
4263
        }
4232
4264
        break;
4233
4265
      case 'n':
4234
4266
        {
4235
 
          char c= '\n';
4236
 
          processed_prompt->append(&c, 1);
 
4267
          processed_prompt->append('\n', 1);
4237
4268
        }
4238
4269
        break;
4239
4270
      case ' ':
4240
4271
      case '_':
4241
4272
        {
4242
 
          char c= ' ';
4243
 
          processed_prompt->append(&c, 1);
 
4273
          processed_prompt->append(' ', 1);
4244
4274
        }
4245
4275
        break;
4246
4276
      case 'R':
4324
4354
 
4325
4355
static void init_username()
4326
4356
{
4327
 
  my_free(full_username,MYF(MY_ALLOW_ZERO_PTR));
4328
 
  my_free(part_username,MYF(MY_ALLOW_ZERO_PTR));
 
4357
  free(full_username);
 
4358
  free(part_username);
4329
4359
 
4330
4360
  DRIZZLE_RES *result;
4331
4361
  if (!drizzle_query(&drizzle,"select USER()") &&
4338
4368
  }
4339
4369
}
4340
4370
 
4341
 
static int com_prompt(string *buffer __attribute__((unused)),
4342
 
                      const char *line)
 
4371
static int com_prompt(string *, const char *line)
4343
4372
{
4344
 
  char *ptr=strchr(line, ' ');
4345
 
  prompt_counter = 0;
4346
 
  my_free(current_prompt, MYF(MY_ALLOW_ZERO_PTR));
4347
 
  current_prompt= strdup(ptr ? ptr+1 : default_prompt);
4348
 
  if (!ptr)
 
4373
  const char *ptr=strchr(line, ' ');
 
4374
  if (ptr == NULL)
4349
4375
    tee_fprintf(stdout, "Returning to default PROMPT of %s\n",
4350
4376
                default_prompt);
 
4377
  prompt_counter = 0;
 
4378
  char * tmpptr= strdup(ptr ? ptr+1 : default_prompt);
 
4379
  if (tmpptr == NULL)
 
4380
    tee_fprintf(stdout, "Memory allocation error. Not changing prompt\n");
4351
4381
  else
 
4382
  {
 
4383
    free(current_prompt);
 
4384
    current_prompt= tmpptr;
4352
4385
    tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
 
4386
  }
4353
4387
  return 0;
4354
4388
}
4355
4389
 
4356
4390
/*
4357
4391
    strcont(str, set) if str contanies any character in the string set.
4358
 
    The result is the position of the first found character in str, or NullS
 
4392
    The result is the position of the first found character in str, or NULL
4359
4393
    if there isn't anything found.
4360
4394
*/
4361
4395