~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzle.c

  • Committer: Jay Pipes
  • Date: 2008-07-17 17:44:14 UTC
  • mfrom: (177 drizzle)
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717174414-sm1e9agb2fjw2ncz
Merged in from trunk.

Made following changes:

libdrizzle/
  client.c
  * Removed DBUG symbols entirely
  * Removed mysql_debug() calls and command line options
  libdrizzle.c
  * Removed DBUG symbols
include/my_sys.h
  * Removed MY_DONT_FREE_DBUG symbol (used in my_end())
mysys/my_init.h
  * Removed MY_DONT_FREE_DBUG symbol (used in my_end())

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2008 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 MySQL
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
15
20
 
16
21
/* mysql command tool
17
22
 * Commands compatible with mSQL by David J. Hughes
44
49
#include <locale.h>
45
50
#endif
46
51
 
 
52
#include <glib.h>
 
53
 
47
54
const char *VER= "14.14";
48
55
 
49
56
/* Don't try to make a nice table if the data is too big */
57
64
 
58
65
void* sql_alloc(unsigned size);      // Don't use mysqld alloc for these
59
66
void sql_element_free(void *ptr);
60
 
#include "sql_string.h"
61
67
 
62
 
extern "C" {
63
68
#if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
64
69
#include <curses.h>
65
70
#include <term.h>
89
94
#undef bcmp                             // Fix problem with new readline
90
95
 
91
96
#include <readline/readline.h>
92
 
#define HAVE_READLINE
93
97
 
94
 
  //int vidattr(long unsigned int attrs);       // Was missing in sun curses
95
 
}
96
98
 
97
99
#if !defined(HAVE_VIDATTR)
98
100
#undef vidattr
128
130
 
129
131
static MYSQL mysql;                     /* The connection */
130
132
static bool ignore_errors=0,wait_flag=0,quick=0,
131
 
               connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
132
 
               opt_rehash=1,skip_updates=0,safe_updates=0,one_database=0,
133
 
               opt_compress=0, using_opt_local_infile=0,
134
 
               vertical=0, line_numbers=1, column_names=1,opt_html=0,
135
 
               opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
136
 
               tty_password= 0, opt_nobeep=0, opt_reconnect=1,
137
 
               default_charset_used= 0, opt_secure_auth= 0,
138
 
               default_pager_set= 0, opt_sigint_ignore= 0,
139
 
               auto_vertical_output= 0,
140
 
               show_warnings= 0, executing_query= 0, interrupted_query= 0;
 
133
  connected=0,opt_raw_data=0,unbuffered=0,output_tables=0,
 
134
  opt_rehash=1,skip_updates=0,safe_updates=0,one_database=0,
 
135
  opt_compress=0, using_opt_local_infile=0,
 
136
  vertical=0, line_numbers=1, column_names=1,opt_html=0,
 
137
  opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
 
138
  tty_password= 0, opt_nobeep=0, opt_reconnect=1,
 
139
  default_charset_used= 0, opt_secure_auth= 0,
 
140
  default_pager_set= 0, opt_sigint_ignore= 0,
 
141
  auto_vertical_output= 0,
 
142
  show_warnings= 0, executing_query= 0, interrupted_query= 0;
141
143
static bool debug_info_flag, debug_check_flag;
142
144
static bool column_types_flag;
143
145
static bool preserve_comments= 0;
147
149
static char * opt_mysql_unix_port=0;
148
150
static int connect_flag=CLIENT_INTERACTIVE;
149
151
static char *current_host,*current_db,*current_user=0,*opt_password=0,
150
 
            *current_prompt=0, *delimiter_str= 0,
151
 
            *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
 
152
  *delimiter_str= 0,*current_prompt=0,
 
153
  *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
152
154
static char *histfile;
153
155
static char *histfile_tmp;
154
 
static String glob_buffer,old_buffer;
155
 
static String processed_prompt;
156
 
static char *full_username=0,*part_username=0,*default_prompt=0;
 
156
static GString *glob_buffer;
 
157
static GString *processed_prompt= NULL;
 
158
static GString *default_prompt= NULL;
 
159
static char *full_username=0,*part_username=0;
157
160
static int wait_time = 5;
158
161
static STATUS status;
159
162
static uint32_t select_limit;
169
172
};
170
173
static const char *day_names[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
171
174
static const char *month_names[]={"Jan","Feb","Mar","Apr","May","Jun","Jul",
172
 
                            "Aug","Sep","Oct","Nov","Dec"};
 
175
                                  "Aug","Sep","Oct","Nov","Dec"};
173
176
static char default_pager[FN_REFLEN];
174
177
static char pager[FN_REFLEN], outfile[FN_REFLEN];
175
178
static FILE *PAGER, *OUTFILE;
183
186
static CHARSET_INFO *charset_info= &my_charset_latin1;
184
187
 
185
188
const char *default_dbug_option="d:t:o,/tmp/mysql.trace";
 
189
int mysql_real_query_for_lazy(const char *buf, int length);
 
190
int mysql_store_result_for_lazy(MYSQL_RES **result);
 
191
 
186
192
 
187
193
void tee_fprintf(FILE *file, const char *fmt, ...);
188
194
void tee_fputs(const char *s, FILE *file);
191
197
static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
192
198
/* The names of functions that actually do the manipulation. */
193
199
static int get_options(int argc,char **argv);
194
 
extern "C" bool get_one_option(int optid, const struct my_option *opt,
195
 
                                  char *argument);
196
 
static int com_quit(String *str,char*),
197
 
           com_go(String *str,char*), com_ego(String *str,char*),
198
 
           com_print(String *str,char*),
199
 
           com_help(String *str,char*), com_clear(String *str,char*),
200
 
           com_connect(String *str,char*), com_status(String *str,char*),
201
 
           com_use(String *str,char*), com_source(String *str, char*),
202
 
           com_rehash(String *str, char*), com_tee(String *str, char*),
203
 
           com_notee(String *str, char*), com_charset(String *str,char*),
204
 
           com_prompt(String *str, char*), com_delimiter(String *str, char*),
205
 
     com_warnings(String *str, char*), com_nowarnings(String *str, char*);
206
 
 
207
 
#ifdef USE_POPEN
208
 
static int com_nopager(String *str, char*), com_pager(String *str, char*),
209
 
           com_edit(String *str,char*), com_shell(String *str, char *);
210
 
#endif
 
200
bool get_one_option(int optid, const struct my_option *opt,
 
201
                    char *argument);
 
202
static int com_quit(GString *str,char*),
 
203
  com_go(GString *str,char*), com_ego(GString *str,char*),
 
204
  com_print(GString *str,char*),
 
205
  com_help(GString *str,char*), com_clear(GString *str,char*),
 
206
  com_connect(GString *str,char*), com_status(GString *str,char*),
 
207
  com_use(GString *str,char*), com_source(GString *str, char*),
 
208
  com_rehash(GString *str, char*), com_tee(GString *str, char*),
 
209
  com_notee(GString *str, char*), com_charset(GString *str,char*),
 
210
  com_prompt(GString *str, char*), com_delimiter(GString *str, char*),
 
211
  com_warnings(GString *str, char*), com_nowarnings(GString *str, char*),
 
212
  com_nopager(GString *str, char*), com_pager(GString *str, char*);
211
213
 
212
214
static int read_and_execute(bool interactive);
213
215
static int sql_connect(char *host,char *database,char *user,char *password,
214
 
                       uint silent);
 
216
                       uint silent);
215
217
static const char *server_version_string(MYSQL *mysql);
216
 
static int put_info(const char *str,INFO_TYPE info,uint error=0,
217
 
                    const char *sql_state=0);
 
218
static int put_info(const char *str,INFO_TYPE info,uint error,
 
219
                    const char *sql_state);
218
220
static int put_error(MYSQL *mysql);
219
221
static void safe_put_field(const char *pos,ulong length);
220
222
static void xmlencode_print(const char *src, uint length);
221
 
static void init_pager();
222
 
static void end_pager();
 
223
static void init_pager(void);
 
224
static void end_pager(void);
223
225
static void init_tee(const char *);
224
 
static void end_tee();
225
 
static const char* construct_prompt();
 
226
static void end_tee(void);
 
227
static const char* construct_prompt(void);
226
228
static char *get_arg(char *line, bool get_next_arg);
227
 
static void init_username();
 
229
static void init_username(void);
228
230
static void add_int_to_prompt(int toadd);
229
231
static int get_result_width(MYSQL_RES *res);
230
232
static int get_field_disp_length(MYSQL_FIELD * field);
231
233
 
232
234
/* A structure which contains information on the commands this program
233
235
   can understand. */
234
 
 
235
236
typedef struct {
236
237
  const char *name;             /* User printable name of the function. */
237
238
  char cmd_char;                /* msql command character */
238
 
  int (*func)(String *str,char *); /* Function to call to do the job. */
 
239
  int (*func)(GString *str,char *); /* Function to call to do the job. */
239
240
  bool takes_params;            /* Max parameters for command */
240
241
  const char *doc;              /* Documentation for this function.  */
241
242
} COMMANDS;
242
243
 
 
244
 
243
245
static COMMANDS commands[] = {
244
246
  { "?",      '?', com_help,   1, "Synonym for `help'." },
245
247
  { "clear",  'c', com_clear,  0, "Clear command."},
247
249
    "Reconnect to the server. Optional arguments are db and host." },
248
250
  { "delimiter", 'd', com_delimiter,    1,
249
251
    "Set statement delimiter. NOTE: Takes the rest of the line as new delimiter." },
250
 
#ifdef USE_POPEN
251
 
  { "edit",   'e', com_edit,   0, "Edit command with $EDITOR."},
252
 
#endif
253
252
  { "ego",    'G', com_ego,    0,
254
253
    "Send command to mysql server, display result vertically."},
255
254
  { "exit",   'q', com_quit,   0, "Exit mysql. Same as quit."},
256
255
  { "go",     'g', com_go,     0, "Send command to mysql server." },
257
256
  { "help",   'h', com_help,   1, "Display this help." },
258
 
#ifdef USE_POPEN
259
257
  { "nopager",'n', com_nopager,0, "Disable pager, print to stdout." },
260
 
#endif
261
258
  { "notee",  't', com_notee,  0, "Don't write into outfile." },
262
 
#ifdef USE_POPEN
263
 
  { "pager",  'P', com_pager,  1, 
 
259
  { "pager",  'P', com_pager,  1,
264
260
    "Set PAGER [to_pager]. Print the query results via PAGER." },
265
 
#endif
266
261
  { "print",  'p', com_print,  0, "Print current command." },
267
262
  { "prompt", 'R', com_prompt, 1, "Change your mysql prompt."},
268
263
  { "quit",   'q', com_quit,   0, "Quit mysql." },
270
265
  { "source", '.', com_source, 1,
271
266
    "Execute an SQL script file. Takes a file name as an argument."},
272
267
  { "status", 's', com_status, 0, "Get status information from the server."},
273
 
#ifdef USE_POPEN
274
 
  { "system", '!', com_shell,  1, "Execute a system shell command."},
275
 
#endif
276
 
  { "tee",    'T', com_tee,    1, 
 
268
  { "tee",    'T', com_tee,    1,
277
269
    "Set outfile [to_outfile]. Append everything into given outfile." },
278
270
  { "use",    'u', com_use,    1,
279
271
    "Use another database. Takes database name as argument." },
383
375
  { "DAY_MICROSECOND", 0, 0, 0, ""},
384
376
  { "DAY_MINUTE", 0, 0, 0, ""},
385
377
  { "DAY_SECOND", 0, 0, 0, ""},
386
 
  { "DEALLOCATE", 0, 0, 0, ""},     
 
378
  { "DEALLOCATE", 0, 0, 0, ""},
387
379
  { "DEC", 0, 0, 0, ""},
388
380
  { "DECIMAL", 0, 0, 0, ""},
389
381
  { "DECLARE", 0, 0, 0, ""},
1000
992
static const char *embedded_server_groups[]=
1001
993
{ "server", "mysql_SERVER", 0 };
1002
994
 
1003
 
extern "C" int history_length;
 
995
int history_length;
1004
996
static int not_in_history(const char *line);
1005
 
static void initialize_readline (char *name);
1006
 
static void fix_history(String *final_command);
 
997
static void initialize_readline (const char *name);
 
998
static void fix_history(GString *final_command);
1007
999
 
1008
1000
static COMMANDS *find_command(char *name,char cmd_name);
1009
 
static bool add_line(String &buffer,char *line,char *in_string,
 
1001
static bool add_line(GString *buffer,char *line,char *in_string,
1010
1002
                     bool *ml_comment);
1011
 
static void remove_cntrl(String &buffer);
 
1003
static void remove_cntrl(GString *buffer);
1012
1004
static void print_table_data(MYSQL_RES *result);
1013
1005
static void print_table_data_html(MYSQL_RES *result);
1014
1006
static void print_table_data_xml(MYSQL_RES *result);
1019
1011
static void end_timer(ulong start_time,char *buff);
1020
1012
static void mysql_end_timer(ulong start_time,char *buff);
1021
1013
static void nice_time(double sec,char *buff,bool part_second);
1022
 
extern "C" sig_handler mysql_end(int sig);
1023
 
extern "C" sig_handler handle_sigint(int sig);
 
1014
extern sig_handler mysql_end(int sig);
 
1015
extern sig_handler handle_sigint(int sig);
1024
1016
#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
1025
1017
static sig_handler window_resize(int sig);
1026
1018
#endif
1030
1022
  char buff[80];
1031
1023
 
1032
1024
  MY_INIT(argv[0]);
1033
 
 
1034
1025
  delimiter_str= delimiter;
1035
 
  default_prompt = my_strdup(getenv("MYSQL_PS1") ? 
1036
 
                             getenv("MYSQL_PS1") : 
1037
 
                             "drizzle> ",MYF(MY_WME));
1038
 
  current_prompt = my_strdup(default_prompt,MYF(MY_WME));
 
1026
  default_prompt = g_string_new(g_strdup(getenv("DRIZZLE_PS1") ?
 
1027
                                         getenv("DRIZZLE_PS1") :
 
1028
                                         "drizzle>> "));
 
1029
  current_prompt = g_strdup(default_prompt->str);
 
1030
  processed_prompt = g_string_sized_new(16);
1039
1031
  prompt_counter=0;
1040
1032
 
1041
1033
  outfile[0]=0;                 // no (default) outfile
1058
1050
  status.exit_status=1;
1059
1051
 
1060
1052
  {
1061
 
    /* 
1062
 
     The file descriptor-layer may be out-of-sync with the file-number layer,
1063
 
     so we make sure that "stdout" is really open.  If its file is closed then
1064
 
     explicitly close the FD layer. 
 
1053
    /*
 
1054
      The file descriptor-layer may be out-of-sync with the file-number layer,
 
1055
      so we make sure that "stdout" is really open.  If its file is closed then
 
1056
      explicitly close the FD layer.
1065
1057
    */
1066
1058
    int stdout_fileno_copy;
1067
1059
    stdout_fileno_copy= dup(fileno(stdout)); /* Okay if fileno fails. */
1086
1078
    my_end(0);
1087
1079
    exit(1);
1088
1080
  }
1089
 
  if (mysql_server_init(embedded_server_arg_count, embedded_server_args, 
 
1081
  if (mysql_server_init(embedded_server_arg_count, embedded_server_args,
1090
1082
                        (char**) embedded_server_groups))
1091
1083
  {
1092
1084
    put_error(NULL);
1094
1086
    my_end(0);
1095
1087
    exit(1);
1096
1088
  }
1097
 
  glob_buffer.realloc(512);
1098
1089
  completion_hash_init(&ht, 128);
1099
1090
  init_alloc_root(&hash_mem_root, 16384, 0);
1100
1091
  bzero((char*) &mysql, sizeof(mysql));
1101
1092
  if (sql_connect(current_host,current_db,current_user,opt_password,
1102
 
                  opt_silent))
 
1093
                  opt_silent))
1103
1094
  {
1104
1095
    quick= 1;                                   // Avoid history
1105
1096
    status.exit_status= 1;
1122
1113
#endif
1123
1114
 
1124
1115
  put_info("Welcome to the Drizzle client..  Commands end with ; or \\g.",
1125
 
           INFO_INFO);
1126
 
  sprintf((char*) glob_buffer.ptr(),
1127
 
          "Your Drizzle connection id is %u\nServer version: %s\n",
1128
 
          mysql_thread_id(&mysql), server_version_string(&mysql));
1129
 
  put_info((char*) glob_buffer.ptr(),INFO_INFO);
 
1116
           INFO_INFO,0,0);
 
1117
  glob_buffer = g_string_sized_new(512);
 
1118
  g_string_printf(glob_buffer,
 
1119
                  "Your Drizzle connection id is %u\nServer version: %s\n",
 
1120
                  mysql_thread_id(&mysql), server_version_string(&mysql));
 
1121
  put_info(glob_buffer->str,INFO_INFO,0,0);
 
1122
  g_string_truncate(glob_buffer,0);
1130
1123
 
1131
 
#ifdef HAVE_READLINE
1132
 
  initialize_readline((char*) my_progname);
 
1124
  initialize_readline(my_progname);
1133
1125
  if (!status.batch && !quick && !opt_html && !opt_xml)
1134
1126
  {
1135
1127
    /* read-history from file, default ~/.mysql_history*/
1136
1128
    if (getenv("MYSQL_HISTFILE"))
1137
 
      histfile=my_strdup(getenv("MYSQL_HISTFILE"),MYF(MY_WME));
 
1129
      histfile=g_strdup(getenv("MYSQL_HISTFILE"));
1138
1130
    else if (getenv("HOME"))
1139
1131
    {
1140
1132
      histfile=(char*) my_malloc((uint) strlen(getenv("HOME"))
1141
 
                                 + (uint) strlen("/.mysql_history")+2,
1142
 
                                 MYF(MY_WME));
 
1133
                                 + (uint) strlen("/.mysql_history")+2,
 
1134
                                 MYF(MY_WME));
1143
1135
      if (histfile)
1144
 
        sprintf(histfile,"%s/.mysql_history",getenv("HOME"));
 
1136
        sprintf(histfile,"%s/.mysql_history",getenv("HOME"));
1145
1137
      char link_name[FN_REFLEN];
1146
1138
      if (my_readlink(link_name, histfile, 0) == 0 &&
1147
1139
          strncmp(link_name, "/dev/null", 10) == 0)
1154
1146
    if (histfile)
1155
1147
    {
1156
1148
      if (verbose)
1157
 
        tee_fprintf(stdout, "Reading history-file %s\n",histfile);
 
1149
        tee_fprintf(stdout, "Reading history-file %s\n",histfile);
1158
1150
      read_history(histfile);
1159
1151
      if (!(histfile_tmp= (char*) my_malloc((uint) strlen(histfile) + 5,
1160
 
                                            MYF(MY_WME))))
 
1152
                                            MYF(MY_WME))))
1161
1153
      {
1162
 
        fprintf(stderr, "Couldn't allocate memory for temp histfile!\n");
1163
 
        exit(1);
 
1154
        fprintf(stderr, "Couldn't allocate memory for temp histfile!\n");
 
1155
        exit(1);
1164
1156
      }
1165
1157
      sprintf(histfile_tmp, "%s.TMP", histfile);
1166
1158
    }
1167
1159
  }
1168
 
#endif
1169
1160
  sprintf(buff, "%s",
1170
 
#ifndef NOT_YET
1171
 
          "Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n");
1172
 
#else
1173
 
          "Type 'help [[%]function name[%]]' to get help on usage of function.\n");
1174
 
#endif
1175
 
  put_info(buff,INFO_INFO);
 
1161
          "Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n");
 
1162
 
 
1163
  put_info(buff,INFO_INFO,0,0);
1176
1164
  status.exit_status= read_and_execute(!status.batch);
1177
1165
  if (opt_outfile)
1178
1166
    end_tee();
1185
1173
sig_handler mysql_end(int sig)
1186
1174
{
1187
1175
  mysql_close(&mysql);
1188
 
#ifdef HAVE_READLINE
1189
1176
  if (!status.batch && !quick && !opt_html && !opt_xml && histfile)
1190
1177
  {
1191
1178
    /* write-history */
1198
1185
  completion_hash_free(&ht);
1199
1186
  free_root(&hash_mem_root,MYF(0));
1200
1187
 
1201
 
#endif
1202
1188
  if (sig >= 0)
1203
 
    put_info(sig ? "Aborted" : "Bye", INFO_RESULT);
1204
 
  glob_buffer.free();
1205
 
  old_buffer.free();
1206
 
  processed_prompt.free();
 
1189
    put_info(sig ? "Aborted" : "Bye", INFO_RESULT,0,0);
 
1190
  assert(glob_buffer != NULL);
 
1191
  g_string_free(glob_buffer,true);
 
1192
  assert(processed_prompt != NULL);
 
1193
  g_string_free(processed_prompt,true);
 
1194
  assert(default_prompt != NULL);
 
1195
  g_string_free(default_prompt,true);
1207
1196
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
1208
1197
  my_free(opt_mysql_unix_port,MYF(MY_ALLOW_ZERO_PTR));
1209
1198
  my_free(histfile,MYF(MY_ALLOW_ZERO_PTR));
1228
1217
  This function handles sigint calls
1229
1218
  If query is in process, kill query
1230
1219
  no query in process, terminate like previous behavior
1231
 
 */
 
1220
*/
1232
1221
sig_handler handle_sigint(int sig)
1233
1222
{
1234
1223
  char kill_buffer[40];
1235
1224
  MYSQL *kill_mysql= NULL;
1236
1225
 
1237
1226
  /* terminate if no query being executed, or we already tried interrupting */
1238
 
  if (!executing_query || interrupted_query)
 
1227
  if (!executing_query || interrupted_query) {
1239
1228
    goto err;
 
1229
  }
1240
1230
 
1241
1231
  kill_mysql= mysql_init(kill_mysql);
1242
1232
  if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password,
1243
1233
                          "", opt_mysql_port, opt_mysql_unix_port,0))
 
1234
  {
1244
1235
    goto err;
 
1236
  }
1245
1237
 
1246
1238
  /* kill_buffer is always big enough because max length of %lu is 15 */
1247
1239
  sprintf(kill_buffer, "KILL /*!50000 QUERY */ %u", mysql_thread_id(&mysql));
1281
1273
  {"no-auto-rehash", 'A',
1282
1274
   "No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead.",
1283
1275
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1284
 
   {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
1285
 
    "Automatically switch to vertical output mode if the result is wider than the terminal width.",
1286
 
    (char**) &auto_vertical_output, (char**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
1276
  {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
 
1277
   "Automatically switch to vertical output mode if the result is wider than the terminal width.",
 
1278
   (char**) &auto_vertical_output, (char**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1287
1279
  {"batch", 'B',
1288
1280
   "Don't use history file. Disable interactive behavior. (Enables --silent)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1289
1281
  {"character-sets-dir", OPT_CHARSETS_DIR,
1332
1324
   (char**) &opt_local_infile,
1333
1325
   (char**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
1334
1326
  {"no-beep", 'b', "Turn off beep on error.", (char**) &opt_nobeep,
1335
 
   (char**) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 
 
1327
   (char**) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1336
1328
  {"host", 'h', "Connect to host.", (char**) &current_host,
1337
1329
   (char**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1338
1330
  {"html", 'H', "Produce HTML output.", (char**) &opt_html, (char**) &opt_html,
1341
1333
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1342
1334
  {"line-numbers", OPT_LINE_NUMBERS, "Write line numbers for errors.",
1343
1335
   (char**) &line_numbers, (char**) &line_numbers, 0, GET_BOOL,
1344
 
   NO_ARG, 1, 0, 0, 0, 0, 0},  
 
1336
   NO_ARG, 1, 0, 0, 0, 0, 0},
1345
1337
  {"skip-line-numbers", 'L', "Don't write line number for errors. WARNING: -L is deprecated, use long version of this option instead.", 0, 0, 0, GET_NO_ARG,
1346
1338
   NO_ARG, 0, 0, 0, 0, 0, 0},
1347
1339
  {"unbuffered", 'n', "Flush buffer after each query.", (char**) &unbuffered,
1361
1353
  {"one-database", 'o',
1362
1354
   "Only update the default database. This is useful for skipping updates to other database in the update log.",
1363
1355
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1364
 
#ifdef USE_POPEN
1365
1356
  {"pager", OPT_PAGER,
1366
1357
   "Pager to use to display results. If you don't supply an option the default pager is taken from your ENV variable PAGER. Valid pagers are less, more, cat [> filename], etc. See interactive help (\\h) also. This option does not work in batch mode. Disable with --disable-pager. This option is disabled by default.",
1367
1358
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1368
1359
  {"no-pager", OPT_NOPAGER,
1369
1360
   "Disable pager and print to stdout. See interactive help (\\h) also. WARNING: option deprecated; use --disable-pager instead.",
1370
1361
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1371
 
#endif
1372
1362
  {"password", 'p',
1373
1363
   "Password to use when connecting to server. If password is not given it's asked from the tty.",
1374
1364
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1391
1381
  {"raw", 'r', "Write fields without conversion. Used with --batch.",
1392
1382
   (char**) &opt_raw_data, (char**) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1393
1383
   0, 0, 0},
1394
 
  {"reconnect", OPT_RECONNECT, "Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default.", 
 
1384
  {"reconnect", OPT_RECONNECT, "Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default.",
1395
1385
   (char**) &opt_reconnect, (char**) &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
1396
1386
  {"silent", 's', "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,
1397
1387
   0, 0},
1446
1436
   (char**) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ULONG_MAX,
1447
1437
   0, 1, 0},
1448
1438
  {"secure-auth", OPT_SECURE_AUTH, "Refuse client connecting to server if it"
1449
 
    " uses old (pre-4.1.1) protocol", (char**) &opt_secure_auth,
1450
 
    (char**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
1439
   " uses old (pre-4.1.1) protocol", (char**) &opt_secure_auth,
 
1440
   (char**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1451
1441
  {"server-arg", OPT_SERVER_ARG, "Send embedded server this as a parameter.",
1452
1442
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1453
1443
  {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
1454
 
    (char**) &show_warnings, (char**) &show_warnings, 0, GET_BOOL, NO_ARG, 
1455
 
    0, 0, 0, 0, 0, 0},
 
1444
   (char**) &show_warnings, (char**) &show_warnings, 0, GET_BOOL, NO_ARG,
 
1445
   0, 0, 0, 0, 0, 0},
1456
1446
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1457
1447
};
1458
1448
 
1459
1449
 
1460
1450
static void usage(int version)
1461
1451
{
1462
 
#if defined(USE_LIBEDIT_INTERFACE)
1463
 
  const char* readline= "";
1464
 
#else
1465
1452
  const char* readline= "readline";
1466
 
#endif
1467
1453
 
1468
 
#ifdef HAVE_READLINE
1469
1454
  printf("%s  Ver %s Distrib %s, for %s (%s) using %s %s\n",
1470
 
         my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,
 
1455
         my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,
1471
1456
         readline, rl_library_version);
1472
 
#else
1473
 
  printf("%s  Ver %s Distrib %s, for %s (%s)\n", my_progname, VER,
1474
 
        MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
1475
 
#endif
1476
1457
 
1477
1458
  if (version)
1478
1459
    return;
1479
1460
  printf("\
1480
 
Copyright (C) 2000-2008 MySQL AB\n\
1481
 
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
 
1461
Copyright (C) 2000-2008 MySQL AB\n                                      \
 
1462
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n \
1482
1463
and you are welcome to modify and redistribute it under the GPL license\n");
1483
1464
  printf("Usage: %s [OPTIONS] [database]\n", my_progname);
1484
1465
  my_print_help(my_long_options);
1489
1470
 
1490
1471
bool
1491
1472
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1492
 
               char *argument)
 
1473
               char *argument)
1493
1474
{
1494
1475
  switch(optid) {
1495
1476
  case OPT_CHARSETS_DIR:
1500
1481
    default_charset_used= 1;
1501
1482
    break;
1502
1483
  case OPT_DELIMITER:
1503
 
    if (argument == disabled_my_option) 
 
1484
    if (argument == disabled_my_option)
1504
1485
    {
1505
1486
      strmov(delimiter, DEFAULT_DELIMITER);
1506
1487
    }
1507
 
    else 
 
1488
    else
1508
1489
    {
1509
1490
      /* Check that delimiter does not contain a backslash */
1510
 
      if (!strstr(argument, "\\")) 
 
1491
      if (!strstr(argument, "\\"))
1511
1492
      {
1512
1493
        strmake(delimiter, argument, sizeof(delimiter) - 1);
1513
1494
      }
1514
 
      else 
 
1495
      else
1515
1496
      {
1516
 
        put_info("DELIMITER cannot contain a backslash character", INFO_ERROR);
 
1497
        put_info("DELIMITER cannot contain a backslash character",
 
1498
                 INFO_ERROR,0,0);
1517
1499
        return 0;
1518
 
      } 
 
1500
      }
1519
1501
    }
1520
1502
    delimiter_length= (uint)strlen(delimiter);
1521
1503
    delimiter_str= delimiter;
1527
1509
    if (argument == disabled_my_option)
1528
1510
    {
1529
1511
      if (opt_outfile)
1530
 
        end_tee();
 
1512
        end_tee();
1531
1513
    }
1532
1514
    else
1533
1515
      init_tee(argument);
1545
1527
      opt_nopager= 0;
1546
1528
      if (argument && strlen(argument))
1547
1529
      {
1548
 
        default_pager_set= 1;
1549
 
        strmake(pager, argument, sizeof(pager) - 1);
1550
 
        strmov(default_pager, pager);
 
1530
        default_pager_set= 1;
 
1531
        strmake(pager, argument, sizeof(pager) - 1);
 
1532
        strmov(default_pager, pager);
1551
1533
      }
1552
1534
      else if (default_pager_set)
1553
 
        strmov(pager, default_pager);
 
1535
        strmov(pager, default_pager);
1554
1536
      else
1555
 
        opt_nopager= 1;
 
1537
        opt_nopager= 1;
1556
1538
    }
1557
1539
    break;
1558
1540
  case OPT_NOPAGER:
1577
1559
    }
1578
1560
    if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
1579
1561
        !(embedded_server_args[embedded_server_arg_count++]=
1580
 
          my_strdup(argument, MYF(MY_FAE))))
 
1562
          g_strdup(argument)))
1581
1563
    {
1582
 
        put_info("Can't use server argument", INFO_ERROR);
1583
 
        return 0;
 
1564
      put_info("Can't use server argument", INFO_ERROR);
 
1565
      return 0;
1584
1566
    }
1585
1567
#else /*EMBEDDED_LIBRARY */
1586
1568
    printf("WARNING: --server-arg option not supported in this configuration.\n");
1613
1595
    {
1614
1596
      char *start= argument;
1615
1597
      my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
1616
 
      opt_password= my_strdup(argument, MYF(MY_FAE));
 
1598
      opt_password= g_strdup(argument);
1617
1599
      while (*argument) *argument++= 'x';               // Destroy argument
1618
1600
      if (*start)
1619
 
        start[1]=0 ;
 
1601
        start[1]=0 ;
1620
1602
      tty_password= 0;
1621
1603
    }
1622
1604
    else
1660
1642
 
1661
1643
  tmp= (char *) getenv("MYSQL_HOST");
1662
1644
  if (tmp)
1663
 
    current_host= my_strdup(tmp, MYF(MY_WME));
 
1645
    current_host= strdup(tmp);
1664
1646
 
1665
1647
  pagpoint= getenv("PAGER");
1666
1648
  if (!((char*) (pagpoint)))
1691
1673
    opt_reconnect= 0;
1692
1674
    connect_flag= 0; /* Not in interactive mode */
1693
1675
  }
1694
 
  
 
1676
 
1695
1677
  if (strcmp(default_charset, charset_info->csname) &&
1696
 
      !(charset_info= get_charset_by_csname(default_charset, 
1697
 
                                            MY_CS_PRIMARY, MYF(MY_WME))))
 
1678
      !(charset_info= get_charset_by_csname(default_charset,
 
1679
                                            MY_CS_PRIMARY, MYF(MY_WME))))
1698
1680
    exit(1);
1699
1681
  if (argc > 1)
1700
1682
  {
1705
1687
  {
1706
1688
    skip_updates= 0;
1707
1689
    my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
1708
 
    current_db= my_strdup(*argv, MYF(MY_WME));
 
1690
    current_db= g_strdup(*argv);
1709
1691
  }
1710
1692
  if (tty_password)
1711
1693
    opt_password= get_tty_password(NullS);
1718
1700
 
1719
1701
static int read_and_execute(bool interactive)
1720
1702
{
1721
 
  char  *line;
1722
 
  char  in_string=0;
 
1703
  char *line;
 
1704
  char in_string=0;
1723
1705
  ulong line_number=0;
1724
 
  bool ml_comment= 0;  
 
1706
  bool ml_comment= 0;
1725
1707
  COMMANDS *com;
1726
1708
  status.exit_status=1;
1727
 
  
 
1709
 
1728
1710
  for (;;)
1729
1711
  {
1730
1712
    if (!interactive)
1737
1719
        you save the file using "Unicode UTF-8" format.
1738
1720
      */
1739
1721
      if (!line_number &&
1740
 
           (uchar) line[0] == 0xEF &&
1741
 
           (uchar) line[1] == 0xBB &&
1742
 
           (uchar) line[2] == 0xBF)
 
1722
          (uchar) line[0] == 0xEF &&
 
1723
          (uchar) line[1] == 0xBB &&
 
1724
          (uchar) line[2] == 0xBF)
1743
1725
        line+= 3;
1744
1726
      line_number++;
1745
 
      if (!glob_buffer.length())
1746
 
        status.query_start_line=line_number;
 
1727
      if (glob_buffer->len!=0)
 
1728
        status.query_start_line=line_number;
1747
1729
    }
1748
1730
    else
1749
1731
    {
1750
1732
      char *prompt= (char*) (ml_comment ? "   /*> " :
1751
 
                             glob_buffer.is_empty() ?  construct_prompt() :
1752
 
                             !in_string ? "    -> " :
1753
 
                             in_string == '\'' ?
1754
 
                             "    '> " : (in_string == '`' ?
1755
 
                             "    `> " :
1756
 
                             "    \"> "));
1757
 
      if (opt_outfile && glob_buffer.is_empty())
1758
 
        fflush(OUTFILE);
 
1733
                             (glob_buffer->len == 0) ?  construct_prompt() :
 
1734
                             !in_string ? "    -> " :
 
1735
                             in_string == '\'' ?
 
1736
                             "    '> " : (in_string == '`' ?
 
1737
                                          "    `> " :
 
1738
                                          "    \"> "));
 
1739
      if (opt_outfile && (glob_buffer->len==0))
 
1740
        fflush(OUTFILE);
1759
1741
 
1760
1742
      if (opt_outfile)
1761
 
        fputs(prompt, OUTFILE);
 
1743
        fputs(prompt, OUTFILE);
1762
1744
      line= readline(prompt);
1763
 
 
1764
1745
      /*
1765
1746
        When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS
1766
1747
        which may cause coredump.
1767
1748
      */
1768
1749
      if (opt_outfile && line)
1769
 
        fprintf(OUTFILE, "%s\n", line);
 
1750
        fprintf(OUTFILE, "%s\n", line);
1770
1751
    }
1771
 
    if (!line)                                  // End of file
 
1752
    // End of file
 
1753
    if (!line)
1772
1754
    {
1773
1755
      status.exit_status=0;
1774
1756
      break;
1778
1760
      Check if line is a mysql command line
1779
1761
      (We want to allow help, print and clear anywhere at line start
1780
1762
    */
1781
 
    if ((named_cmds || glob_buffer.is_empty())
1782
 
        && !ml_comment && !in_string && (com=find_command(line,0)))
 
1763
    if ((named_cmds || (glob_buffer->len==0))
 
1764
        && !ml_comment && !in_string && (com=find_command(line,0)))
1783
1765
    {
1784
 
      if ((*com->func)(&glob_buffer,line) > 0)
1785
 
        break;
1786
 
      if (glob_buffer.is_empty())               // If buffer was emptied
1787
 
        in_string=0;
1788
 
#ifdef HAVE_READLINE
 
1766
      if ((*com->func)(glob_buffer,line) > 0)
 
1767
        break;
 
1768
      // If buffer was emptied
 
1769
      if (glob_buffer->len==0)
 
1770
        in_string=0;
1789
1771
      if (interactive && status.add_to_history && not_in_history(line))
1790
 
        add_history(line);
1791
 
#endif
 
1772
        add_history(line);
1792
1773
      continue;
1793
1774
    }
1794
1775
    if (add_line(glob_buffer,line,&in_string,&ml_comment))
1799
1780
  if (!interactive && !status.exit_status)
1800
1781
  {
1801
1782
    remove_cntrl(glob_buffer);
1802
 
    if (!glob_buffer.is_empty())
 
1783
    if (glob_buffer->len != 0)
1803
1784
    {
1804
1785
      status.exit_status=1;
1805
 
      if (com_go(&glob_buffer,line) <= 0)
1806
 
        status.exit_status=0;
 
1786
      if (com_go(glob_buffer,line) <= 0)
 
1787
        status.exit_status=0;
1807
1788
    }
1808
1789
  }
1809
1790
 
1841
1822
    {
1842
1823
      len=(uint) (end - name);
1843
1824
      while (my_isspace(charset_info,*end))
1844
 
        end++;
 
1825
        end++;
1845
1826
      if (!*end)
1846
 
        end=0;                                  // no arguments to function
 
1827
        end=0;                                  // no arguments to function
1847
1828
    }
1848
1829
    else
1849
1830
      len=(uint) strlen(name);
1852
1833
  for (uint i= 0; commands[i].name; i++)
1853
1834
  {
1854
1835
    if (commands[i].func &&
1855
 
        ((name && !my_strnncoll(charset_info,(uchar*)name,len, (uchar*)commands[i].name,len) && !commands[i].name[len] && (!end || (end && commands[i].takes_params))) || (!name && commands[i].cmd_char == cmd_char)))
 
1836
        ((name && !my_strnncoll(charset_info,(uchar*)name,len, (uchar*)commands[i].name,len) && !commands[i].name[len] && (!end || (end && commands[i].takes_params))) || (!name && commands[i].cmd_char == cmd_char)))
1856
1837
    {
1857
1838
      return(&commands[i]);
1858
1839
    }
1861
1842
}
1862
1843
 
1863
1844
 
1864
 
static bool add_line(String &buffer,char *line,char *in_string,
1865
 
                     bool *ml_comment)
 
1845
static bool add_line(GString *buffer,char *line,char *in_string,
 
1846
                        bool *ml_comment)
1866
1847
{
1867
1848
  uchar inchar;
1868
1849
  char buff[80], *pos, *out;
1871
1852
  bool ss_comment= 0;
1872
1853
 
1873
1854
 
1874
 
  if (!line[0] && buffer.is_empty())
 
1855
  if (!line[0] && (buffer->len==0))
1875
1856
    return(0);
1876
 
#ifdef HAVE_READLINE
1877
1857
  if (status.add_to_history && line[0] && not_in_history(line))
1878
1858
    add_history(line);
1879
 
#endif
1880
1859
  char *end_of_line=line+(uint) strlen(line);
1881
1860
 
1882
1861
  for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
1885
1864
    {
1886
1865
      // Skip spaces at the beggining of a statement
1887
1866
      if (my_isspace(charset_info,inchar) && (out == line) &&
1888
 
          buffer.is_empty())
 
1867
          (buffer->len==0))
1889
1868
        continue;
1890
1869
    }
1891
 
        
 
1870
 
1892
1871
#ifdef USE_MB
1893
1872
    // Accept multi-byte characters as-is
1894
1873
    int length;
1906
1885
      continue;
1907
1886
    }
1908
1887
#endif
1909
 
    if (!*ml_comment && inchar == '\\' &&
 
1888
        if (!*ml_comment && inchar == '\\' &&
1910
1889
        !(mysql.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES))
1911
1890
    {
1912
1891
      // Found possbile one character command like \c
1913
1892
 
1914
1893
      if (!(inchar = (uchar) *++pos))
1915
 
        break;                          // readline adds one '\'
 
1894
        break;                          // readline adds one '\'
1916
1895
      if (*in_string || inchar == 'N')  // \N is short for NULL
1917
1896
      {                                 // Don't allow commands in string
1918
 
        *out++='\\';
1919
 
        *out++= (char) inchar;
1920
 
        continue;
 
1897
        *out++='\\';
 
1898
        *out++= (char) inchar;
 
1899
        continue;
1921
1900
      }
1922
1901
      if ((com=find_command(NullS,(char) inchar)))
1923
1902
      {
1924
1903
        // Flush previously accepted characters
1925
1904
        if (out != line)
1926
1905
        {
1927
 
          buffer.append(line, (uint) (out-line));
 
1906
          g_string_append_len(buffer, line, (gssize) (out-line));
1928
1907
          out= line;
1929
1908
        }
1930
 
        
1931
 
        if ((*com->func)(&buffer,pos-1) > 0)
 
1909
 
 
1910
        if ((*com->func)(buffer,pos-1) > 0)
1932
1911
          return(1);                       // Quit
1933
1912
        if (com->takes_params)
1934
1913
        {
1951
1930
              ; // Remove parameters
1952
1931
            if (!*pos)
1953
1932
              pos--;
1954
 
            else 
 
1933
            else
1955
1934
              pos+= delimiter_length - 1; // Point at last delim char
1956
1935
          }
1957
1936
        }
1958
1937
      }
1959
1938
      else
1960
1939
      {
1961
 
        sprintf(buff,"Unknown command '\\%c'.",inchar);
1962
 
        if (put_info(buff,INFO_ERROR) > 0)
1963
 
          return(1);
1964
 
        *out++='\\';
1965
 
        *out++=(char) inchar;
1966
 
        continue;
 
1940
        sprintf(buff,"Unknown command '\\%c'.",inchar);
 
1941
        if (put_info(buff,INFO_ERROR,0,0) > 0)
 
1942
          return(1);
 
1943
        *out++='\\';
 
1944
        *out++=(char) inchar;
 
1945
        continue;
1967
1946
      }
1968
1947
    }
1969
1948
    else if (!*ml_comment && !*in_string &&
1974
1953
      // Flush previously accepted characters
1975
1954
      if (out != line)
1976
1955
      {
1977
 
        buffer.append(line, (uint32) (out - line));
 
1956
        g_string_append_len(buffer, line, (gssize) (out - line));
1978
1957
        out= line;
1979
1958
      }
1980
1959
 
1981
1960
      // Flush possible comments in the buffer
1982
 
      if (!buffer.is_empty())
 
1961
      if (buffer->len != 0)
1983
1962
      {
1984
 
        if (com_go(&buffer, 0) > 0) // < 0 is not fatal
 
1963
        if (com_go(buffer, 0) > 0) // < 0 is not fatal
1985
1964
          return(1);
1986
 
        buffer.length(0);
 
1965
        assert(buffer!=NULL);
 
1966
        g_string_truncate(buffer,0);
1987
1967
      }
1988
1968
 
1989
1969
      /*
1990
1970
        Delimiter wants the get rest of the given line as argument to
1991
1971
        allow one to change ';' to ';;' and back
1992
1972
      */
1993
 
      buffer.append(pos);
1994
 
      if (com_delimiter(&buffer, pos) > 0)
 
1973
      g_string_append(buffer,pos);
 
1974
      if (com_delimiter(buffer, pos) > 0)
1995
1975
        return(1);
1996
1976
 
1997
 
      buffer.length(0);
 
1977
      g_string_truncate(buffer,0);
1998
1978
      break;
1999
1979
    }
2000
1980
    else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter))
2010
1990
      // Flush previously accepted characters
2011
1991
      if (out != line)
2012
1992
      {
2013
 
        buffer.append(line, (uint32) (out-line));
 
1993
        g_string_append_len(buffer, line, (gssize) (out-line));
2014
1994
        out= line;
2015
1995
      }
2016
1996
 
2020
2000
                                 my_isspace(charset_info, pos[2]))))
2021
2001
      {
2022
2002
        // Add trailing single line comments to this statement
2023
 
        buffer.append(pos);
 
2003
        g_string_append(buffer, pos);
2024
2004
        pos+= strlen(pos);
2025
2005
      }
2026
2006
 
2027
2007
      pos--;
2028
2008
 
2029
 
      if ((com= find_command(buffer.c_ptr(), 0)))
 
2009
      if ((com= find_command(buffer->str, 0)))
2030
2010
      {
2031
 
          
2032
 
        if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
2033
 
          return(1);                       // Quit 
 
2011
 
 
2012
        if ((*com->func)(buffer, buffer->str) > 0)
 
2013
          return(1);                       // Quit
2034
2014
      }
2035
2015
      else
2036
2016
      {
2037
 
        if (com_go(&buffer, 0) > 0)             // < 0 is not fatal
 
2017
        if (com_go(buffer, 0) > 0)             // < 0 is not fatal
2038
2018
          return(1);
2039
2019
      }
2040
 
      buffer.length(0);
 
2020
      g_string_truncate(buffer,0);
2041
2021
    }
2042
 
    else if (!*ml_comment && (!*in_string && (inchar == '#' ||
2043
 
                              (inchar == '-' && pos[1] == '-' && my_isspace(charset_info,pos[2])))))
 
2022
    else if (!*ml_comment
 
2023
             && (!*in_string
 
2024
                 && (inchar == '#'
 
2025
                     || (inchar == '-'
 
2026
                         && pos[1] == '-'
 
2027
                         && my_isspace(charset_info,pos[2])))))
2044
2028
    {
2045
2029
      // Flush previously accepted characters
2046
2030
      if (out != line)
2047
2031
      {
2048
 
        buffer.append(line, (uint32) (out - line));
 
2032
        g_string_append_len(buffer, line, (gssize) (out - line));
2049
2033
        out= line;
2050
2034
      }
2051
2035
 
2052
2036
      // comment to end of line
2053
2037
      if (preserve_comments)
2054
 
        buffer.append(pos);
 
2038
        g_string_append(buffer,pos);
2055
2039
 
2056
2040
      break;
2057
2041
    }
2058
2042
    else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
2059
 
             *(pos+2) != '!')
 
2043
             *(pos+2) != '!')
2060
2044
    {
2061
2045
      if (preserve_comments)
2062
2046
      {
2068
2052
      *ml_comment= 1;
2069
2053
      if (out != line)
2070
2054
      {
2071
 
        buffer.append(line,(uint) (out-line));
 
2055
        g_string_append_len(buffer, line, (gssize) (out-line));
2072
2056
        out=line;
2073
2057
      }
2074
2058
    }
2084
2068
      *ml_comment= 0;
2085
2069
      if (out != line)
2086
2070
      {
2087
 
        buffer.append(line, (uint32) (out - line));
 
2071
        g_string_append_len(buffer, line, (gssize) (out - line));
2088
2072
        out= line;
2089
2073
      }
2090
2074
      // Consumed a 2 chars or more, and will add 1 at most,
2091
2075
      // so using the 'line' buffer to edit data in place is ok.
2092
2076
      need_space= 1;
2093
 
    }      
 
2077
    }
2094
2078
    else
2095
 
    {                                           // Add found char to buffer
 
2079
    {
 
2080
      // Add found char to buffer
2096
2081
      if (!*in_string && inchar == '/' && *(pos + 1) == '*' &&
2097
2082
          *(pos + 2) == '!')
2098
2083
        ss_comment= 1;
2099
2084
      else if (!*in_string && ss_comment && inchar == '*' && *(pos + 1) == '/')
2100
2085
        ss_comment= 0;
2101
2086
      if (inchar == *in_string)
2102
 
        *in_string= 0;
 
2087
        *in_string= 0;
2103
2088
      else if (!*ml_comment && !*in_string &&
2104
 
               (inchar == '\'' || inchar == '"' || inchar == '`'))
2105
 
        *in_string= (char) inchar;
 
2089
               (inchar == '\'' || inchar == '"' || inchar == '`'))
 
2090
        *in_string= (char) inchar;
2106
2091
      if (!*ml_comment || preserve_comments)
2107
2092
      {
2108
2093
        if (need_space && !my_isspace(charset_info, (char)inchar))
2112
2097
      }
2113
2098
    }
2114
2099
  }
2115
 
  if (out != line || !buffer.is_empty())
 
2100
  if (out != line || (buffer->len > 0))
2116
2101
  {
2117
2102
    *out++='\n';
2118
2103
    uint length=(uint) (out-line);
2119
 
    if (buffer.length() + length >= buffer.alloced_length())
2120
 
      buffer.realloc(buffer.length()+length+IO_SIZE);
2121
 
    if ((!*ml_comment || preserve_comments) && buffer.append(line, length))
 
2104
    if ((!*ml_comment || preserve_comments)
 
2105
        && (g_string_append_len(buffer, line, length) == NULL))
2122
2106
      return(1);
2123
2107
  }
2124
2108
  return(0);
2125
2109
}
2126
2110
 
2127
2111
/*****************************************************************
2128
 
            Interface to Readline Completion
 
2112
            Interface to Readline Completion
2129
2113
******************************************************************/
2130
2114
 
2131
 
#ifdef HAVE_READLINE
2132
2115
 
2133
2116
static char *new_command_generator(const char *text, int);
2134
 
extern "C" char **new_mysql_completion (const char *text, int start, int end);
 
2117
extern char **new_mysql_completion (const char *text, int start, int end);
2135
2118
 
2136
2119
/*
2137
2120
  Tell the GNU Readline library how to complete.  We want to try to complete
2140
2123
*/
2141
2124
 
2142
2125
#if defined(USE_NEW_READLINE_INTERFACE) || defined(USE_LIBEDIT_INTERFACE)
2143
 
extern "C" char *no_completion(const char*,int)
 
2126
extern char *no_completion(const char*,int);
2144
2127
#else
2145
 
extern "C" char *no_completion()
 
2128
char *no_completion(void);
 
2129
char *no_completion(void)
 
2130
{
 
2131
  /* No filename completion */
 
2132
  return 0;
 
2133
}
2146
2134
#endif
2147
 
{
2148
 
  return 0;                                     /* No filename completion */
2149
 
}
2150
2135
 
2151
 
/*      glues pieces of history back together if in pieces   */
2152
 
static void fix_history(String *final_command) 
 
2136
/* glues pieces of history back together if in pieces   */
 
2137
static void fix_history(GString *final_command)
2153
2138
{
2154
2139
  int total_lines = 1;
2155
 
  char *ptr = final_command->c_ptr();
2156
 
  String fixed_buffer;  /* Converted buffer */
 
2140
  const char *ptr = final_command->str;
 
2141
  /* Converted buffer */
 
2142
  GString * fixed_buffer;
 
2143
  fixed_buffer = g_string_sized_new(16);
2157
2144
  char str_char = '\0';  /* Character if we are in a string or not */
2158
 
  
 
2145
 
2159
2146
  /* find out how many lines we have and remove newlines */
2160
 
  while (*ptr != '\0') 
 
2147
  while (*ptr != '\0')
2161
2148
  {
2162
2149
    switch (*ptr) {
2163
2150
      /* string character */
2164
2151
    case '"':
2165
2152
    case '\'':
2166
2153
    case '`':
2167
 
      if (str_char == '\0')     /* open string */
2168
 
        str_char = *ptr;
 
2154
      // open string
 
2155
      if (str_char == '\0')
 
2156
        str_char = *ptr;
2169
2157
      else if (str_char == *ptr)   /* close string */
2170
 
        str_char = '\0';
2171
 
      fixed_buffer.append(ptr,1);
 
2158
        str_char = '\0';
 
2159
      g_string_append_len(fixed_buffer, ptr, 1);
2172
2160
      break;
2173
2161
    case '\n':
2174
 
      /* 
2175
 
         not in string, change to space
2176
 
         if in string, leave it alone 
 
2162
      /*
 
2163
        not in string, change to space
 
2164
        if in string, leave it alone
2177
2165
      */
2178
 
      fixed_buffer.append(str_char == '\0' ? " " : "\n");
 
2166
      g_string_append(fixed_buffer,(str_char == '\0') ? " " : "\n");
2179
2167
      total_lines++;
2180
2168
      break;
2181
2169
    case '\\':
2182
 
      fixed_buffer.append('\\');
 
2170
      g_string_append_c(fixed_buffer, '\\');
2183
2171
      /* need to see if the backslash is escaping anything */
2184
 
      if (str_char) 
 
2172
      if (str_char)
2185
2173
      {
2186
 
        ptr++;
2187
 
        /* special characters that need escaping */
2188
 
        if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
2189
 
          fixed_buffer.append(ptr,1);
2190
 
        else
2191
 
          ptr--;
 
2174
        ptr++;
 
2175
        /* special characters that need escaping */
 
2176
        if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
 
2177
          g_string_append_len(fixed_buffer, ptr, 1);
 
2178
        else
 
2179
          ptr--;
2192
2180
      }
2193
2181
      break;
2194
 
      
2195
2182
    default:
2196
 
      fixed_buffer.append(ptr,1);
 
2183
      g_string_append_len(fixed_buffer, ptr, 1);
2197
2184
    }
2198
2185
    ptr++;
2199
2186
  }
2200
 
  if (total_lines > 1)                  
2201
 
    add_history(fixed_buffer.ptr());
 
2187
  if (total_lines > 1)
 
2188
    add_history(fixed_buffer->str);
2202
2189
}
2203
2190
 
2204
 
/*      
 
2191
/*
2205
2192
  returns 0 if line matches the previous history entry
2206
2193
  returns 1 if the line doesn't match the previous history entry
2207
2194
*/
2208
 
static int not_in_history(const char *line) 
 
2195
static int not_in_history(const char *line)
2209
2196
{
2210
2197
  HIST_ENTRY *oldhist = history_get(history_length);
2211
 
  
 
2198
 
2212
2199
  if (oldhist == 0)
2213
2200
    return 1;
2214
2201
  if (strcmp(oldhist->line,line) == 0)
2216
2203
  return 1;
2217
2204
}
2218
2205
 
2219
 
static void initialize_readline (char *name)
 
2206
static void initialize_readline (const char *name)
2220
2207
{
2221
2208
  /* Allow conditional parsing of the ~/.inputrc file. */
2222
2209
  rl_readline_name= name;
2262
2249
 
2263
2250
      b = find_all_matches(&ht,text,(uint) strlen(text),&len);
2264
2251
      if (!b)
2265
 
        return NullS;
 
2252
        return NullS;
2266
2253
      e = b->pData;
2267
2254
    }
2268
2255
 
2269
2256
    if (e)
2270
2257
    {
2271
 
      ptr= strdup(e->str);
 
2258
      ptr= g_strdup(e->str);
2272
2259
      e = e->pNext;
2273
2260
      return ptr;
2274
2261
    }
2281
2268
      /* find the first used bucket */
2282
2269
      for (i=0 ; i < ht.nTableSize ; i++)
2283
2270
      {
2284
 
        if (ht.arBuckets[i])
2285
 
        {
2286
 
          b = ht.arBuckets[i];
2287
 
          e = b->pData;
2288
 
          break;
2289
 
        }
 
2271
        if (ht.arBuckets[i])
 
2272
        {
 
2273
          b = ht.arBuckets[i];
 
2274
          e = b->pData;
 
2275
          break;
 
2276
        }
2290
2277
      }
2291
2278
    }
2292
2279
    ptr= NullS;
2293
2280
    while (e && !ptr)
2294
2281
    {                                   /* find valid entry in bucket */
2295
2282
      if ((uint) strlen(e->str) == b->nKeyLength)
2296
 
        ptr = strdup(e->str);
 
2283
        ptr = g_strdup(e->str);
2297
2284
      /* find the next used entry */
2298
2285
      e = e->pNext;
2299
2286
      if (!e)
2300
2287
      { /* find the next used bucket */
2301
 
        b = b->pNext;
2302
 
        if (!b)
2303
 
        {
2304
 
          for (i++ ; i<ht.nTableSize; i++)
2305
 
          {
2306
 
            if (ht.arBuckets[i])
2307
 
            {
2308
 
              b = ht.arBuckets[i];
2309
 
              e = b->pData;
2310
 
              break;
2311
 
            }
2312
 
          }
2313
 
        }
2314
 
        else
2315
 
          e = b->pData;
 
2288
        b = b->pNext;
 
2289
        if (!b)
 
2290
        {
 
2291
          for (i++ ; i<ht.nTableSize; i++)
 
2292
          {
 
2293
            if (ht.arBuckets[i])
 
2294
            {
 
2295
              b = ht.arBuckets[i];
 
2296
              e = b->pData;
 
2297
              break;
 
2298
            }
 
2299
          }
 
2300
        }
 
2301
        else
 
2302
          e = b->pData;
2316
2303
      }
2317
2304
    }
2318
2305
    if (ptr)
2359
2346
  if (mysql_query(&mysql,"show databases") == 0)
2360
2347
  {
2361
2348
    if (!(databases = mysql_store_result(&mysql)))
2362
 
      put_info(mysql_error(&mysql),INFO_INFO);
 
2349
      put_info(mysql_error(&mysql),INFO_INFO,0,0);
2363
2350
    else
2364
2351
    {
2365
2352
      while ((database_row=mysql_fetch_row(databases)))
2366
2353
      {
2367
 
        char *str=strdup_root(&hash_mem_root, (char*) database_row[0]);
2368
 
        if (str)
2369
 
          add_word(&ht,(char*) str);
 
2354
        char *str=strdup_root(&hash_mem_root, (char*) database_row[0]);
 
2355
        if (str)
 
2356
          add_word(&ht,(char*) str);
2370
2357
      }
2371
2358
      mysql_free_result(databases);
2372
2359
    }
2375
2362
  if (mysql_query(&mysql,"show tables")==0)
2376
2363
  {
2377
2364
    if (!(tables = mysql_store_result(&mysql)))
2378
 
      put_info(mysql_error(&mysql),INFO_INFO);
 
2365
      put_info(mysql_error(&mysql),INFO_INFO,0,0);
2379
2366
    else
2380
2367
    {
2381
2368
      if (mysql_num_rows(tables) > 0 && !opt_silent && write_info)
2382
2369
      {
2383
 
        tee_fprintf(stdout, "\
2384
 
Reading table information for completion of table and column names\n\
 
2370
        tee_fprintf(stdout, "\
 
2371
Reading table information for completion of table and column names\n    \
2385
2372
You can turn off this feature to get a quicker startup with -A\n\n");
2386
2373
      }
2387
2374
      while ((table_row=mysql_fetch_row(tables)))
2388
2375
      {
2389
 
        char *str=strdup_root(&hash_mem_root, (char*) table_row[0]);
2390
 
        if (str &&
2391
 
            !completion_hash_exists(&ht,(char*) str, (uint) strlen(str)))
2392
 
          add_word(&ht,str);
 
2376
        char *str=strdup_root(&hash_mem_root, (char*) table_row[0]);
 
2377
        if (str &&
 
2378
            !completion_hash_exists(&ht,(char*) str, (uint) strlen(str)))
 
2379
          add_word(&ht,str);
2393
2380
      }
2394
2381
    }
2395
2382
  }
2401
2388
  }
2402
2389
  mysql_data_seek(tables,0);
2403
2390
  if (!(field_names= (char ***) alloc_root(&hash_mem_root,sizeof(char **) *
2404
 
                                           (uint) (mysql_num_rows(tables)+1))))
 
2391
                                           (uint) (mysql_num_rows(tables)+1))))
2405
2392
  {
2406
2393
    mysql_free_result(tables);
2407
2394
    return;
2413
2400
    {
2414
2401
      num_fields=mysql_num_fields(fields);
2415
2402
      if (!(field_names[i] = (char **) alloc_root(&hash_mem_root,
2416
 
                                                  sizeof(char *) *
2417
 
                                                  (num_fields*2+1))))
 
2403
                                                  sizeof(char *) *
 
2404
                                                  (num_fields*2+1))))
2418
2405
      {
2419
2406
        mysql_free_result(fields);
2420
2407
        break;
2423
2410
      j=0;
2424
2411
      while ((sql_field=mysql_fetch_field(fields)))
2425
2412
      {
2426
 
        sprintf(buf,"%.64s.%.64s",table_row[0],sql_field->name);
2427
 
        field_names[i][j] = strdup_root(&hash_mem_root,buf);
2428
 
        add_word(&ht,field_names[i][j]);
2429
 
        field_names[i][num_fields+j] = strdup_root(&hash_mem_root,
2430
 
                                                   sql_field->name);
2431
 
        if (!completion_hash_exists(&ht,field_names[i][num_fields+j],
2432
 
                                    (uint) strlen(field_names[i][num_fields+j])))
2433
 
          add_word(&ht,field_names[i][num_fields+j]);
2434
 
        j++;
 
2413
        sprintf(buf,"%.64s.%.64s",table_row[0],sql_field->name);
 
2414
        field_names[i][j] = strdup_root(&hash_mem_root,buf);
 
2415
        add_word(&ht,field_names[i][j]);
 
2416
        field_names[i][num_fields+j] = strdup_root(&hash_mem_root,
 
2417
                                                   sql_field->name);
 
2418
        if (!completion_hash_exists(&ht,field_names[i][num_fields+j],
 
2419
                                    (uint) strlen(field_names[i][num_fields+j])))
 
2420
          add_word(&ht,field_names[i][num_fields+j]);
 
2421
        j++;
2435
2422
      }
2436
2423
      mysql_free_result(fields);
2437
2424
    }
2445
2432
  return;
2446
2433
}
2447
2434
 
2448
 
        /* for gnu readline */
 
2435
/* for gnu readline */
2449
2436
 
2450
2437
#ifndef HAVE_INDEX
2451
2438
extern "C" {
2452
 
extern char *index(const char *,int c),*rindex(const char *,int);
2453
 
 
2454
 
char *index(const char *s,int c)
2455
 
{
2456
 
  for (;;)
2457
 
  {
2458
 
     if (*s == (char) c) return (char*) s;
2459
 
     if (!*s++) return NullS;
2460
 
  }
2461
 
}
2462
 
 
2463
 
char *rindex(const char *s,int c)
2464
 
{
2465
 
  register char *t;
2466
 
 
2467
 
  t = NullS;
2468
 
  do if (*s == (char) c) t = (char*) s; while (*s++);
2469
 
  return (char*) t;
2470
 
}
 
2439
  extern char *index(const char *,int c),*rindex(const char *,int);
 
2440
 
 
2441
  char *index(const char *s,int c)
 
2442
  {
 
2443
    for (;;)
 
2444
    {
 
2445
      if (*s == (char) c) return (char*) s;
 
2446
      if (!*s++) return NullS;
 
2447
    }
 
2448
  }
 
2449
 
 
2450
  char *rindex(const char *s,int c)
 
2451
  {
 
2452
    register char *t;
 
2453
 
 
2454
    t = NullS;
 
2455
    do if (*s == (char) c) t = (char*) s; while (*s++);
 
2456
    return (char*) t;
 
2457
  }
2471
2458
}
2472
2459
#endif
2473
 
#endif /* HAVE_READLINE */
2474
2460
 
2475
2461
 
2476
2462
static int reconnect(void)
2478
2464
  /* purecov: begin tested */
2479
2465
  if (opt_reconnect)
2480
2466
  {
2481
 
    put_info("No connection. Trying to reconnect...",INFO_INFO);
2482
 
    (void) com_connect((String *) 0, 0);
 
2467
    put_info("No connection. Trying to reconnect...",INFO_INFO,0,0);
 
2468
    (void) com_connect((GString *) 0, 0);
2483
2469
    if (opt_rehash)
2484
2470
      com_rehash(NULL, NULL);
2485
2471
  }
2486
2472
  if (!connected)
2487
 
    return put_info("Can't connect to the server\n",INFO_ERROR);
 
2473
    return put_info("Can't connect to the server\n",INFO_ERROR,0,0);
2488
2474
  /* purecov: end */
2489
2475
  return 0;
2490
2476
}
2491
2477
 
2492
 
static void get_current_db()
 
2478
static void get_current_db(void)
2493
2479
{
2494
2480
  MYSQL_RES *res;
2495
2481
 
2501
2487
  {
2502
2488
    MYSQL_ROW row= mysql_fetch_row(res);
2503
2489
    if (row[0])
2504
 
      current_db= my_strdup(row[0], MYF(MY_WME));
 
2490
      current_db= g_strdup(row[0]);
2505
2491
    mysql_free_result(res);
2506
2492
  }
2507
2493
}
2541
2527
  char ccat= (*cur)[num_cat][0];
2542
2528
  if (*last_char != ccat)
2543
2529
  {
2544
 
    put_info(ccat == 'Y' ? "categories:" : "topics:", INFO_INFO);
 
2530
    put_info(ccat == 'Y' ? "categories:" : "topics:", INFO_INFO,0,0);
2545
2531
    *last_char= ccat;
2546
2532
  }
2547
2533
  tee_fprintf(PAGER, "   %s\n", (*cur)[num_name]);
2548
2534
}
2549
2535
 
2550
2536
 
2551
 
static int com_server_help(String *buffer __attribute__((unused)),
2552
 
                           char *line __attribute__((unused)), char *help_arg)
 
2537
static int com_server_help(GString *buffer,
 
2538
                           char *line __attribute__((unused)),
 
2539
                           char *help_arg)
2553
2540
{
2554
2541
  MYSQL_ROW cur;
2555
 
  const char *server_cmd= buffer->ptr();
 
2542
  const char *server_cmd= buffer->str;
2556
2543
  char cmd_buf[100];
2557
2544
  MYSQL_RES *result;
2558
2545
  int error;
2559
 
  
 
2546
 
2560
2547
  if (help_arg[0] != '\'')
2561
2548
  {
2562
 
        char *end_arg= strend(help_arg);
2563
 
        if(--end_arg)
2564
 
        {
2565
 
                while (my_isspace(charset_info,*end_arg))
2566
 
          end_arg--;
2567
 
                *++end_arg= '\0';
2568
 
        }
2569
 
        (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
 
2549
    char *end_arg= strend(help_arg);
 
2550
    if(--end_arg)
 
2551
    {
 
2552
      while (my_isspace(charset_info,*end_arg))
 
2553
        end_arg--;
 
2554
      *++end_arg= '\0';
 
2555
    }
 
2556
    (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
2570
2557
    server_cmd= cmd_buf;
2571
2558
  }
2572
 
  
2573
 
  if (!status.batch)
2574
 
  {
2575
 
    old_buffer= *buffer;
2576
 
    old_buffer.copy();
2577
 
  }
2578
2559
 
2579
2560
  if (!connected && reconnect())
2580
2561
    return 1;
2592
2573
    {
2593
2574
      if (!(cur= mysql_fetch_row(result)))
2594
2575
      {
2595
 
        error= -1;
2596
 
        goto err;
 
2576
        error= -1;
 
2577
        goto err;
2597
2578
      }
2598
2579
 
2599
2580
      init_pager();
2600
2581
      tee_fprintf(PAGER,   "Name: \'%s\'\n", cur[0]);
2601
2582
      tee_fprintf(PAGER,   "Description:\n%s", cur[1]);
2602
2583
      if (cur[2] && *((char*)cur[2]))
2603
 
        tee_fprintf(PAGER, "Examples:\n%s", cur[2]);
 
2584
        tee_fprintf(PAGER, "Examples:\n%s", cur[2]);
2604
2585
      tee_fprintf(PAGER,   "\n");
2605
2586
      end_pager();
2606
2587
    }
2613
2594
 
2614
2595
      if (num_fields == 2)
2615
2596
      {
2616
 
        put_info("Many help items for your request exist.", INFO_INFO);
2617
 
        put_info("To make a more specific request, please type 'help <item>',\nwhere <item> is one of the following", INFO_INFO);
2618
 
        num_name= 0;
2619
 
        num_cat= 1;
 
2597
        put_info("Many help items for your request exist.", INFO_INFO,0,0);
 
2598
        put_info("To make a more specific request, please type 'help <item>',\nwhere <item> is one of the following", INFO_INFO,0,0);
 
2599
        num_name= 0;
 
2600
        num_cat= 1;
2620
2601
      }
2621
2602
      else if ((cur= mysql_fetch_row(result)))
2622
2603
      {
2623
 
        tee_fprintf(PAGER, "You asked for help about help category: \"%s\"\n", cur[0]);
2624
 
        put_info("For more information, type 'help <item>', where <item> is one of the following", INFO_INFO);
2625
 
        num_name= 1;
2626
 
        num_cat= 2;
2627
 
        print_help_item(&cur,1,2,&last_char);
 
2604
        tee_fprintf(PAGER, "You asked for help about help category: \"%s\"\n", cur[0]);
 
2605
        put_info("For more information, type 'help <item>', where <item> is one of the following", INFO_INFO,0,0);
 
2606
        num_name= 1;
 
2607
        num_cat= 2;
 
2608
        print_help_item(&cur,1,2,&last_char);
2628
2609
      }
2629
2610
 
2630
2611
      while ((cur= mysql_fetch_row(result)))
2631
 
        print_help_item(&cur,num_name,num_cat,&last_char);
 
2612
        print_help_item(&cur,num_name,num_cat,&last_char);
2632
2613
      tee_fprintf(PAGER, "\n");
2633
2614
      end_pager();
2634
2615
    }
2635
2616
    else
2636
2617
    {
2637
 
      put_info("\nNothing found", INFO_INFO);
2638
 
      put_info("Please try to run 'help contents' for a list of all accessible topics\n", INFO_INFO);
 
2618
      put_info("\nNothing found", INFO_INFO,0,0);
 
2619
      put_info("Please try to run 'help contents' for a list of all accessible topics\n", INFO_INFO,0,0);
2639
2620
    }
2640
2621
  }
2641
2622
 
2645
2626
}
2646
2627
 
2647
2628
static int
2648
 
com_help(String *buffer __attribute__((unused)),
2649
 
         char *line __attribute__((unused)))
 
2629
com_help(GString *buffer __attribute__((unused)),
 
2630
         char *line __attribute__((unused)))
2650
2631
{
2651
2632
  register int i, j;
2652
2633
  char * help_arg= strchr(line,' '), buff[32], *end;
2654
2635
  {
2655
2636
    while (my_isspace(charset_info,*help_arg))
2656
2637
      help_arg++;
2657
 
        if (*help_arg)    
2658
 
          return com_server_help(buffer,line,help_arg);
 
2638
    if (*help_arg)
 
2639
      return com_server_help(buffer,line,help_arg);
2659
2640
  }
2660
2641
 
2661
 
  put_info("List of all Drizzle commands:", INFO_INFO);
 
2642
  put_info("List of all Drizzle commands:", INFO_INFO,0,0);
2662
2643
  if (!named_cmds)
2663
 
    put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
 
2644
    put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO,0,0);
2664
2645
  for (i = 0; commands[i].name; i++)
2665
2646
  {
2666
2647
    end= strmov(buff, commands[i].name);
2668
2649
      end= strmov(end, " ");
2669
2650
    if (commands[i].func)
2670
2651
      tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
2671
 
                  commands[i].cmd_char, commands[i].doc);
 
2652
                  commands[i].cmd_char, commands[i].doc);
2672
2653
  }
2673
2654
  if (connected && mysql_get_server_version(&mysql) >= 40100)
2674
 
    put_info("\nFor server side help, type 'help contents'\n", INFO_INFO);
 
2655
    put_info("\nFor server side help, type 'help contents'\n", INFO_INFO,0,0);
2675
2656
  return 0;
2676
2657
}
2677
2658
 
2678
2659
 
2679
 
        /* ARGSUSED */
2680
2660
static int
2681
 
com_clear(String *buffer,char *line __attribute__((unused)))
 
2661
com_clear(GString *buffer,char *line __attribute__((unused)))
2682
2662
{
2683
 
#ifdef HAVE_READLINE
2684
2663
  if (status.add_to_history)
2685
2664
    fix_history(buffer);
2686
 
#endif
2687
 
  buffer->length(0);
 
2665
  g_string_truncate(buffer, 0);
2688
2666
  return 0;
2689
2667
}
2690
2668
 
2691
 
        /* ARGSUSED */
2692
2669
static int
2693
 
com_charset(String *buffer __attribute__((unused)), char *line)
 
2670
com_charset(GString *buffer __attribute__((unused)), char *line)
2694
2671
{
2695
2672
  char buff[256], *param;
2696
2673
  CHARSET_INFO * new_cs;
2698
2675
  param= get_arg(buff, 0);
2699
2676
  if (!param || !*param)
2700
2677
  {
2701
 
    return put_info("Usage: \\C char_setname | charset charset_name", 
2702
 
                    INFO_ERROR, 0);
 
2678
    return put_info("Usage: \\C char_setname | charset charset_name",
 
2679
                    INFO_ERROR, 0, 0);
2703
2680
  }
2704
2681
  new_cs= get_charset_by_csname(param, MY_CS_PRIMARY, MYF(MY_WME));
2705
2682
  if (new_cs)
2708
2685
    mysql_set_character_set(&mysql, charset_info->csname);
2709
2686
    default_charset= (char *)charset_info->csname;
2710
2687
    default_charset_used= 1;
2711
 
    put_info("Charset changed", INFO_INFO);
 
2688
    put_info("Charset changed", INFO_INFO,0,0);
2712
2689
  }
2713
 
  else put_info("Charset is not found", INFO_INFO);
 
2690
  else put_info("Charset is not found", INFO_INFO,0,0);
2714
2691
  return 0;
2715
2692
}
2716
2693
 
2717
2694
/*
2718
2695
  Execute command
2719
2696
  Returns: 0  if ok
2720
 
          -1 if not fatal error
2721
 
          1  if fatal error
 
2697
  -1 if not fatal error
 
2698
  1  if fatal error
2722
2699
*/
2723
 
 
2724
 
 
2725
2700
static int
2726
 
com_go(String *buffer,char *line __attribute__((unused)))
 
2701
com_go(GString *buffer,
 
2702
       char *line __attribute__((unused)))
2727
2703
{
2728
 
  char          buff[200]; /* about 110 chars used so far */
2729
 
  char          time_buff[52+3+1]; /* time max + space&parens + NUL */
2730
 
  MYSQL_RES     *result;
2731
 
  ulong         timer, warnings= 0;
2732
 
  uint          error= 0;
 
2704
  char          buff[200]; /* about 110 chars used so far */
 
2705
  char          time_buff[52+3+1]; /* time max + space&parens + NUL */
 
2706
  MYSQL_RES     *result;
 
2707
  ulong         timer, warnings= 0;
 
2708
  uint          error= 0;
2733
2709
  int           err= 0;
2734
2710
 
2735
2711
  interrupted_query= 0;
2736
 
  if (!status.batch)
2737
 
  {
2738
 
    old_buffer= *buffer;                        // Save for edit command
2739
 
    old_buffer.copy();
2740
 
  }
2741
2712
 
2742
2713
  /* Remove garbage for nicer messages */
2743
 
  remove_cntrl(*buffer);
 
2714
  remove_cntrl(buffer);
2744
2715
 
2745
 
  if (buffer->is_empty())
 
2716
  if (buffer->len == 0)
2746
2717
  {
2747
 
    if (status.batch)                           // Ignore empty quries
 
2718
    // Ignore empty quries
 
2719
    if (status.batch)
2748
2720
      return 0;
2749
 
    return put_info("No query specified\n",INFO_ERROR);
 
2721
    return put_info("No query specified\n",INFO_ERROR,0,0);
2750
2722
 
2751
2723
  }
2752
2724
  if (!connected && reconnect())
2753
2725
  {
2754
 
    buffer->length(0);                          // Remove query on error
 
2726
    // Remove query on error
 
2727
    g_string_truncate(buffer, 0);
2755
2728
    return opt_reconnect ? -1 : 1;          // Fatal error
2756
2729
  }
2757
2730
  if (verbose)
2758
 
    (void) com_print(buffer,0);
 
2731
    (void) com_print(buffer, 0);
2759
2732
 
2760
2733
  if (skip_updates &&
2761
 
      (buffer->length() < 4 || my_strnncoll(charset_info,
2762
 
                                            (const uchar*)buffer->ptr(),4,
2763
 
                                            (const uchar*)"SET ",4)))
 
2734
      ((buffer->len < 4)
 
2735
      || g_string_equal(g_string_new_len(buffer->str,4),
 
2736
                        g_string_new("SET "))))
2764
2737
  {
2765
 
    (void) put_info("Ignoring query to other database",INFO_INFO);
 
2738
    (void) put_info("Ignoring query to other database",INFO_INFO,0,0);
2766
2739
    return 0;
2767
2740
  }
2768
2741
 
2769
2742
  timer=start_timer();
2770
2743
  executing_query= 1;
2771
 
  error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length());
 
2744
  error= mysql_real_query_for_lazy(buffer->str,buffer->len);
2772
2745
 
2773
 
#ifdef HAVE_READLINE
2774
 
  if (status.add_to_history) 
2775
 
  {  
2776
 
    buffer->append(vertical ? "\\G" : delimiter);
 
2746
  if (status.add_to_history)
 
2747
  {
 
2748
    g_string_append(buffer, vertical ? "\\G" : delimiter);
2777
2749
    /* Append final command onto history */
2778
2750
    fix_history(buffer);
2779
2751
  }
2780
 
#endif
2781
2752
 
2782
 
  buffer->length(0);
 
2753
  g_string_truncate(buffer, 0);
2783
2754
 
2784
2755
  if (error)
2785
2756
    goto end;
2813
2784
    {
2814
2785
      if (!mysql_num_rows(result) && ! quick && !column_types_flag)
2815
2786
      {
2816
 
        strmov(buff, "Empty set");
 
2787
        strmov(buff, "Empty set");
2817
2788
        if (opt_xml)
2818
 
        { 
 
2789
        {
2819
2790
          /*
2820
2791
            We must print XML header and footer
2821
2792
            to produce a well-formed XML even if
2828
2799
      }
2829
2800
      else
2830
2801
      {
2831
 
        init_pager();
2832
 
        if (opt_html)
2833
 
          print_table_data_html(result);
2834
 
        else if (opt_xml)
2835
 
          print_table_data_xml(result);
2836
 
  else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
2837
 
          print_table_data_vertically(result);
2838
 
        else if (opt_silent && verbose <= 2 && !output_tables)
2839
 
          print_tab_data(result);
2840
 
        else
2841
 
          print_table_data(result);
2842
 
        sprintf(buff,"%ld %s in set",
2843
 
                (long) mysql_num_rows(result),
2844
 
                (long) mysql_num_rows(result) == 1 ? "row" : "rows");
2845
 
        end_pager();
 
2802
        init_pager();
 
2803
        if (opt_html)
 
2804
          print_table_data_html(result);
 
2805
        else if (opt_xml)
 
2806
          print_table_data_xml(result);
 
2807
        else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
 
2808
          print_table_data_vertically(result);
 
2809
        else if (opt_silent && verbose <= 2 && !output_tables)
 
2810
          print_tab_data(result);
 
2811
        else
 
2812
          print_table_data(result);
 
2813
        sprintf(buff,"%ld %s in set",
 
2814
                (long) mysql_num_rows(result),
 
2815
                (long) mysql_num_rows(result) == 1 ? "row" : "rows");
 
2816
        end_pager();
2846
2817
        if (mysql_errno(&mysql))
2847
2818
          error= put_error(&mysql);
2848
2819
      }
2851
2822
      strmov(buff,"Query OK");
2852
2823
    else
2853
2824
      sprintf(buff,"Query OK, %ld %s affected",
2854
 
              (long) mysql_affected_rows(&mysql),
2855
 
              (long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows");
 
2825
              (long) mysql_affected_rows(&mysql),
 
2826
              (long) mysql_affected_rows(&mysql) == 1 ? "row" : "rows");
2856
2827
 
2857
2828
    pos=strend(buff);
2858
2829
    if ((warnings= mysql_warning_count(&mysql)))
2862
2833
      pos=int10_to_str(warnings, pos, 10);
2863
2834
      pos=strmov(pos, " warning");
2864
2835
      if (warnings != 1)
2865
 
        *pos++= 's';
 
2836
        *pos++= 's';
2866
2837
    }
2867
2838
    strmov(pos, time_buff);
2868
 
    put_info(buff,INFO_RESULT);
 
2839
    put_info(buff,INFO_RESULT,0,0);
2869
2840
    if (mysql_info(&mysql))
2870
 
      put_info(mysql_info(&mysql),INFO_RESULT);
2871
 
    put_info("",INFO_RESULT);                   // Empty row
 
2841
      put_info(mysql_info(&mysql),INFO_RESULT,0,0);
 
2842
    put_info("",INFO_RESULT,0,0);                       // Empty row
2872
2843
 
2873
2844
    if (result && !mysql_eof(result))   /* Something wrong when using quick */
2874
2845
      error= put_error(&mysql);
2881
2852
 
2882
2853
end:
2883
2854
 
2884
 
 /* Show warnings if any or error occured */
 
2855
  /* Show warnings if any or error occured */
2885
2856
  if (show_warnings == 1 && (warnings >= 1 || error))
2886
2857
    print_warnings();
2887
2858
 
2888
 
  if (!error && !status.batch && 
 
2859
  if (!error && !status.batch &&
2889
2860
      (mysql.server_status & SERVER_STATUS_DB_DROPPED))
2890
2861
    get_current_db();
2891
2862
 
2896
2867
 
2897
2868
static void init_pager()
2898
2869
{
2899
 
#ifdef USE_POPEN
2900
2870
  if (!opt_nopager)
2901
2871
  {
2902
2872
    if (!(PAGER= popen(pager, "w")))
2906
2876
    }
2907
2877
  }
2908
2878
  else
2909
 
#endif
2910
2879
    PAGER= stdout;
2911
2880
}
2912
2881
 
2913
2882
static void end_pager()
2914
2883
{
2915
 
#ifdef USE_POPEN
2916
2884
  if (!opt_nopager)
2917
2885
    pclose(PAGER);
2918
 
#endif
2919
2886
}
2920
2887
 
2921
2888
 
2947
2914
 
2948
2915
 
2949
2916
static int
2950
 
com_ego(String *buffer,char *line)
 
2917
com_ego(GString *buffer,char *line)
2951
2918
{
2952
2919
  int result;
2953
2920
  bool oldvertical=vertical;
2986
2953
  static char buf[1024];
2987
2954
  char *s=buf;
2988
2955
  *s=0;
2989
 
#define ff2s_check_flag(X) \
2990
 
                if (f & X ## _FLAG) { s=strmov(s, # X " "); f &= ~ X ## _FLAG; }
 
2956
#define ff2s_check_flag(X)                                              \
 
2957
  if (f & X ## _FLAG) { s=strmov(s, # X " "); f &= ~ X ## _FLAG; }
2991
2958
  ff2s_check_flag(NOT_NULL);
2992
2959
  ff2s_check_flag(PRI_KEY);
2993
2960
  ff2s_check_flag(UNIQUE_KEY);
3022
2989
  while ((field = mysql_fetch_field(result)))
3023
2990
  {
3024
2991
    tee_fprintf(PAGER, "Field %3u:  `%s`\n"
3025
 
                       "Catalog:    `%s`\n"
3026
 
                       "Database:   `%s`\n"
3027
 
                       "Table:      `%s`\n"
3028
 
                       "Org_table:  `%s`\n"
3029
 
                       "Type:       %s\n"
3030
 
                       "Collation:  %s (%u)\n"
3031
 
                       "Length:     %lu\n"
3032
 
                       "Max_length: %lu\n"
3033
 
                       "Decimals:   %u\n"
3034
 
                       "Flags:      %s\n\n",
 
2992
                "Catalog:    `%s`\n"
 
2993
                "Database:   `%s`\n"
 
2994
                "Table:      `%s`\n"
 
2995
                "Org_table:  `%s`\n"
 
2996
                "Type:       %s\n"
 
2997
                "Collation:  %s (%u)\n"
 
2998
                "Length:     %lu\n"
 
2999
                "Max_length: %lu\n"
 
3000
                "Decimals:   %u\n"
 
3001
                "Flags:      %s\n\n",
3035
3002
                ++i,
3036
3003
                field->name, field->catalog, field->db, field->table,
3037
3004
                field->org_table, fieldtype2str(field->type),
3046
3013
static void
3047
3014
print_table_data(MYSQL_RES *result)
3048
3015
{
3049
 
  String separator(256);
3050
 
  MYSQL_ROW     cur;
3051
 
  MYSQL_FIELD   *field;
3052
 
  bool          *num_flag;
 
3016
  GString       *separator = g_string_sized_new(256);
 
3017
  MYSQL_ROW     cur;
 
3018
  MYSQL_FIELD   *field;
 
3019
  bool          *num_flag;
3053
3020
 
3054
 
  num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result));
 
3021
  num_flag=(bool*) my_malloc(sizeof(bool)*mysql_num_fields(result),
 
3022
                             MYF(MY_WME));
3055
3023
  if (column_types_flag)
3056
3024
  {
3057
3025
    print_field_types(result);
3059
3027
      return;
3060
3028
    mysql_field_seek(result,0);
3061
3029
  }
3062
 
  separator.copy("+",1,charset_info);
 
3030
  separator = g_string_append_c(separator, '+');
3063
3031
  while ((field = mysql_fetch_field(result)))
3064
3032
  {
3065
3033
    uint length= column_names ? field->name_length : 0;
3068
3036
    else
3069
3037
      length=max(length,field->max_length);
3070
3038
    if (length < 4 && !IS_NOT_NULL(field->flags))
3071
 
      length=4;                                 // Room for "NULL"
 
3039
      // Room for "NULL"
 
3040
      length=4;
3072
3041
    field->max_length=length;
3073
 
    separator.fill(separator.length()+length+2,'-');
3074
 
    separator.append('+');
 
3042
    uint x;
 
3043
    for (x=0; x< (length+2); x++)
 
3044
      g_string_append_c(separator, '-');
 
3045
    g_string_append_c(separator, '+');
3075
3046
  }
3076
 
  separator.append('\0');                       // End marker for \0
3077
 
  tee_puts((char*) separator.ptr(), PAGER);
 
3047
  // End marker for \0
 
3048
  // TODO: Huh? Do we need this with GString?
 
3049
  g_string_append_c(separator, '\0');
 
3050
 
 
3051
  tee_puts((char*) separator->str, PAGER);
3078
3052
  if (column_names)
3079
3053
  {
3080
3054
    mysql_field_seek(result,0);
3087
3061
                                                  field->name + name_length);
3088
3062
      uint display_length= field->max_length + name_length - numcells;
3089
3063
      tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
3090
 
                                            MAX_COLUMN_LENGTH),
 
3064
                                             MAX_COLUMN_LENGTH),
3091
3065
                  field->name);
3092
3066
      num_flag[off]= IS_NUM(field->type);
3093
3067
    }
3094
3068
    (void) tee_fputs("\n", PAGER);
3095
 
    tee_puts((char*) separator.ptr(), PAGER);
 
3069
    tee_puts((char*) separator->str, PAGER);
3096
3070
  }
3097
3071
 
3098
3072
  while ((cur= mysql_fetch_row(result)))
3114
3088
      {
3115
3089
        buffer= "NULL";
3116
3090
        data_length= 4;
3117
 
      } 
3118
 
      else 
 
3091
      }
 
3092
      else
3119
3093
      {
3120
3094
        buffer= cur[off];
3121
3095
        data_length= (uint) lengths[off];
3124
3098
      field= mysql_fetch_field(result);
3125
3099
      field_max_length= field->max_length;
3126
3100
 
3127
 
      /* 
3128
 
       How many text cells on the screen will this string span?  If it contains
3129
 
       multibyte characters, then the number of characters we occupy on screen
3130
 
       will be fewer than the number of bytes we occupy in memory.
 
3101
      /*
 
3102
        How many text cells on the screen will this string span?  If it contains
 
3103
        multibyte characters, then the number of characters we occupy on screen
 
3104
        will be fewer than the number of bytes we occupy in memory.
3131
3105
 
3132
 
       We need to find how much screen real-estate we will occupy to know how 
3133
 
       many extra padding-characters we should send with the printing function.
 
3106
        We need to find how much screen real-estate we will occupy to know how
 
3107
        many extra padding-characters we should send with the printing function.
3134
3108
      */
3135
3109
      visible_length= charset_info->cset->numcells(charset_info, buffer, buffer + data_length);
3136
3110
      extra_padding= data_length - visible_length;
3141
3115
      {
3142
3116
        if (num_flag[off] != 0) /* if it is numeric, we right-justify it */
3143
3117
          tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, TRUE);
3144
 
        else 
3145
 
          tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, FALSE);
 
3118
        else
 
3119
          tee_print_sized_data(buffer, data_length,
 
3120
                               field_max_length+extra_padding, FALSE);
3146
3121
      }
3147
3122
      tee_fputs(" | ", PAGER);
3148
3123
    }
3149
3124
    (void) tee_fputs("\n", PAGER);
3150
3125
  }
3151
 
  tee_puts((char*) separator.ptr(), PAGER);
3152
 
  my_afree((uchar*) num_flag);
 
3126
  tee_puts(separator->str, PAGER);
 
3127
  my_free(num_flag, MYF(MY_ALLOW_ZERO_PTR));
3153
3128
}
3154
3129
 
3155
3130
/**
3156
 
  Return the length of a field after it would be rendered into text.
3157
 
 
3158
 
  This doesn't know or care about multibyte characters.  Assume we're
3159
 
  using such a charset.  We can't know that all of the upcoming rows 
3160
 
  for this column will have bytes that each render into some fraction
3161
 
  of a character.  It's at least possible that a row has bytes that 
3162
 
  all render into one character each, and so the maximum length is 
3163
 
  still the number of bytes.  (Assumption 1:  This can't be better 
3164
 
  because we can never know the number of characters that the DB is 
3165
 
  going to send -- only the number of bytes.  2: Chars <= Bytes.)
3166
 
 
3167
 
  @param  field  Pointer to a field to be inspected
3168
 
 
3169
 
  @returns  number of character positions to be used, at most
 
3131
   Return the length of a field after it would be rendered into text.
 
3132
 
 
3133
   This doesn't know or care about multibyte characters.  Assume we're
 
3134
   using such a charset.  We can't know that all of the upcoming rows
 
3135
   for this column will have bytes that each render into some fraction
 
3136
   of a character.  It's at least possible that a row has bytes that
 
3137
   all render into one character each, and so the maximum length is
 
3138
   still the number of bytes.  (Assumption 1:  This can't be better
 
3139
   because we can never know the number of characters that the DB is
 
3140
   going to send -- only the number of bytes.  2: Chars <= Bytes.)
 
3141
 
 
3142
   @param  field  Pointer to a field to be inspected
 
3143
 
 
3144
   @returns  number of character positions to be used, at most
3170
3145
*/
3171
3146
static int get_field_disp_length(MYSQL_FIELD *field)
3172
3147
{
3184
3159
}
3185
3160
 
3186
3161
/**
3187
 
  For a new result, return the max number of characters that any
3188
 
  upcoming row may return.
3189
 
 
3190
 
  @param  result  Pointer to the result to judge
3191
 
 
3192
 
  @returns  The max number of characters in any row of this result
 
3162
   For a new result, return the max number of characters that any
 
3163
   upcoming row may return.
 
3164
 
 
3165
   @param  result  Pointer to the result to judge
 
3166
 
 
3167
   @returns  The max number of characters in any row of this result
3193
3168
*/
3194
3169
static int get_result_width(MYSQL_RES *result)
3195
3170
{
3196
3171
  unsigned int len= 0;
3197
3172
  MYSQL_FIELD *field;
3198
3173
  MYSQL_FIELD_OFFSET offset;
3199
 
  
 
3174
 
3200
3175
  offset= mysql_field_tell(result);
3201
3176
  assert(offset == 0);
3202
3177
 
3203
3178
  while ((field= mysql_fetch_field(result)) != NULL)
3204
3179
    len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
3205
3180
 
3206
 
  (void) mysql_field_seek(result, offset);      
 
3181
  (void) mysql_field_seek(result, offset);
3207
3182
 
3208
3183
  return len + 1; /* plus final bar. */
3209
3184
}
3211
3186
static void
3212
3187
tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified)
3213
3188
{
3214
 
  /* 
 
3189
  /*
3215
3190
    For '\0's print ASCII spaces instead, as '\0' is eaten by (at
3216
3191
    least my) console driver, and that messes up the pretty table
3217
 
    grid.  (The \0 is also the reason we can't use fprintf() .) 
 
3192
    grid.  (The \0 is also the reason we can't use fprintf() .)
3218
3193
  */
3219
3194
  unsigned int i;
3220
3195
  const char *p;
3221
3196
 
3222
 
  if (right_justified) 
 
3197
  if (right_justified)
3223
3198
    for (i= data_length; i < total_bytes_to_send; i++)
3224
3199
      tee_putc((int)' ', PAGER);
3225
3200
 
3231
3206
      tee_putc((int)*p, PAGER);
3232
3207
  }
3233
3208
 
3234
 
  if (! right_justified) 
 
3209
  if (! right_justified)
3235
3210
    for (i= data_length; i < total_bytes_to_send; i++)
3236
3211
      tee_putc((int)' ', PAGER);
3237
3212
}
3250
3225
  {
3251
3226
    while((field = mysql_fetch_field(result)))
3252
3227
    {
3253
 
      tee_fprintf(PAGER, "<TH>%s</TH>", (field->name ? 
3254
 
                                         (field->name[0] ? field->name : 
3255
 
                                          " &nbsp; ") : "NULL"));
 
3228
      tee_fprintf(PAGER, "<TH>%s</TH>", (field->name ?
 
3229
                                         (field->name[0] ? field->name :
 
3230
                                          " &nbsp; ") : "NULL"));
3256
3231
    }
3257
3232
    (void) tee_fputs("</TR>", PAGER);
3258
3233
  }
3260
3235
  {
3261
3236
    if (interrupted_query)
3262
3237
      break;
3263
 
    uint32_t *lengths= mysql_fetch_lengths(result);
 
3238
    uint32_t *lengths=mysql_fetch_lengths(result);
3264
3239
    (void) tee_fputs("<TR>", PAGER);
3265
3240
    for (uint32_t i= 0; i < mysql_num_fields(result); i++)
3266
3241
    {
3283
3258
  mysql_field_seek(result,0);
3284
3259
 
3285
3260
  tee_fputs("<?xml version=\"1.0\"?>\n\n<resultset statement=\"", PAGER);
3286
 
  xmlencode_print(glob_buffer.ptr(), (int)strlen(glob_buffer.ptr()));
 
3261
  xmlencode_print(glob_buffer->str, glob_buffer->len);
3287
3262
  tee_fputs("\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">",
3288
3263
            PAGER);
3289
3264
 
3292
3267
  {
3293
3268
    if (interrupted_query)
3294
3269
      break;
3295
 
    uint32_t *lengths= mysql_fetch_lengths(result);
 
3270
    uint32_t *lengths=mysql_fetch_lengths(result);
3296
3271
    (void) tee_fputs("\n  <row>\n", PAGER);
3297
3272
    for (uint i=0; i < mysql_num_fields(result); i++)
3298
3273
    {
3334
3309
    if (interrupted_query)
3335
3310
      break;
3336
3311
    mysql_field_seek(result,0);
3337
 
    tee_fprintf(PAGER, 
3338
 
                "*************************** %d. row ***************************\n", row_count);
 
3312
    tee_fprintf(PAGER,
 
3313
                "*************************** %d. row ***************************\n", row_count);
3339
3314
    for (uint off=0; off < mysql_num_fields(result); off++)
3340
3315
    {
3341
3316
      field= mysql_fetch_field(result);
3407
3382
    tee_fputs("NULL", PAGER);
3408
3383
  else
3409
3384
  {
3410
 
    for (const char *p = src; *p && length; *p++, length--)
 
3385
    for (const char *p = src; *p && length; length--)
3411
3386
    {
3412
3387
      const char *t;
3413
 
      if ((t = array_value(xmlmeta, *p)))
3414
 
        tee_fputs(t, PAGER);
 
3388
      if ((t = array_value(xmlmeta, *p++)))
 
3389
        tee_fputs(t, PAGER);
3415
3390
      else
3416
 
        tee_putc(*p, PAGER);
 
3391
        tee_putc(*p, PAGER);
3417
3392
    }
3418
3393
  }
3419
3394
}
3429
3404
    if (opt_raw_data)
3430
3405
      tee_fputs(pos, PAGER);
3431
3406
    else for (const char *end=pos+length ; pos != end ; pos++)
3432
 
    {
 
3407
         {
3433
3408
#ifdef USE_MB
3434
 
      int l;
3435
 
      if (use_mb(charset_info) &&
3436
 
          (l = my_ismbchar(charset_info, pos, end)))
3437
 
      {
3438
 
          while (l--)
3439
 
            tee_putc(*pos++, PAGER);
3440
 
          pos--;
3441
 
          continue;
3442
 
      }
 
3409
           int l;
 
3410
           if (use_mb(charset_info) &&
 
3411
               (l = my_ismbchar(charset_info, pos, end)))
 
3412
           {
 
3413
             while (l--)
 
3414
               tee_putc(*pos++, PAGER);
 
3415
             pos--;
 
3416
             continue;
 
3417
           }
3443
3418
#endif
3444
 
      if (!*pos)
3445
 
        tee_fputs("\\0", PAGER); // This makes everything hard
3446
 
      else if (*pos == '\t')
3447
 
        tee_fputs("\\t", PAGER); // This would destroy tab format
3448
 
      else if (*pos == '\n')
3449
 
        tee_fputs("\\n", PAGER); // This too
3450
 
      else if (*pos == '\\')
3451
 
        tee_fputs("\\\\", PAGER);
3452
 
        else
3453
 
        tee_putc(*pos, PAGER);
3454
 
    }
 
3419
           if (!*pos)
 
3420
             tee_fputs("\\0", PAGER); // This makes everything hard
 
3421
           else if (*pos == '\t')
 
3422
             tee_fputs("\\t", PAGER); // This would destroy tab format
 
3423
           else if (*pos == '\n')
 
3424
             tee_fputs("\\n", PAGER); // This too
 
3425
           else if (*pos == '\\')
 
3426
             tee_fputs("\\\\", PAGER);
 
3427
           else
 
3428
             tee_putc(*pos, PAGER);
 
3429
         }
3455
3430
  }
3456
3431
}
3457
3432
 
3469
3444
    while ((field = mysql_fetch_field(result)))
3470
3445
    {
3471
3446
      if (first++)
3472
 
        (void) tee_fputs("\t", PAGER);
 
3447
        (void) tee_fputs("\t", PAGER);
3473
3448
      (void) tee_fputs(field->name, PAGER);
3474
3449
    }
3475
3450
    (void) tee_fputs("\n", PAGER);
3488
3463
}
3489
3464
 
3490
3465
static int
3491
 
com_tee(String *buffer __attribute__((__unused__)), char *line )
 
3466
com_tee(GString *buffer __attribute__((__unused__)), char *line )
3492
3467
{
3493
3468
  char file_name[FN_REFLEN], *end, *param;
3494
3469
 
3517
3492
    param++;
3518
3493
  end= strmake(file_name, param, sizeof(file_name) - 1);
3519
3494
  /* remove end space from command line */
3520
 
  while (end > file_name && (my_isspace(charset_info,end[-1]) || 
3521
 
                             my_iscntrl(charset_info,end[-1])))
 
3495
  while (end > file_name && (my_isspace(charset_info,end[-1]) ||
 
3496
                             my_iscntrl(charset_info,end[-1])))
3522
3497
    end--;
3523
3498
  end[0]= 0;
3524
3499
  if (end == file_name)
3532
3507
 
3533
3508
 
3534
3509
static int
3535
 
com_notee(String *buffer __attribute__((unused)),
3536
 
          char *line __attribute__((unused)))
 
3510
com_notee(GString *buffer __attribute__((unused)),
 
3511
          char *line __attribute__((unused)))
3537
3512
{
3538
3513
  if (opt_outfile)
3539
3514
    end_tee();
3545
3520
  Sorry, this command is not available in Windows.
3546
3521
*/
3547
3522
 
3548
 
#ifdef USE_POPEN
3549
3523
static int
3550
 
com_pager(String *buffer, char *line __attribute__((unused)))
 
3524
com_pager(GString *buffer __attribute__((__unused__)),
 
3525
          char *line __attribute__((unused)))
3551
3526
{
3552
3527
  char pager_name[FN_REFLEN], *end, *param;
3553
3528
 
3576
3551
  else
3577
3552
  {
3578
3553
    end= strmake(pager_name, param, sizeof(pager_name)-1);
3579
 
    while (end > pager_name && (my_isspace(charset_info,end[-1]) || 
 
3554
    while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
3580
3555
                                my_iscntrl(charset_info,end[-1])))
3581
3556
      end--;
3582
3557
    end[0]=0;
3590
3565
 
3591
3566
 
3592
3567
static int
3593
 
com_nopager(String *buffer __attribute__((unused)),
3594
 
            char *line __attribute__((unused)))
 
3568
com_nopager(GString *buffer __attribute__((unused)),
 
3569
            char *line __attribute__((unused)))
3595
3570
{
3596
3571
  strmov(pager, "stdout");
3597
3572
  opt_nopager=1;
3599
3574
  tee_fprintf(stdout, "PAGER set to stdout\n");
3600
3575
  return 0;
3601
3576
}
3602
 
#endif
3603
 
 
3604
 
 
3605
 
/*
3606
 
  Sorry, you can't send the result to an editor in Win32
3607
 
*/
3608
 
 
3609
 
#ifdef USE_POPEN
3610
 
static int
3611
 
com_edit(String *buffer,char *line __attribute__((unused)))
3612
 
{
3613
 
  char  filename[FN_REFLEN],buff[160];
3614
 
  int   fd,tmp;
3615
 
  const char *editor;
3616
 
 
3617
 
  if ((fd=create_temp_file(filename,NullS,"sql", O_CREAT | O_WRONLY,
3618
 
                           MYF(MY_WME))) < 0)
3619
 
    goto err;
3620
 
  if (buffer->is_empty() && !old_buffer.is_empty())
3621
 
    (void) my_write(fd,(uchar*) old_buffer.ptr(),old_buffer.length(),
3622
 
                    MYF(MY_WME));
3623
 
  else
3624
 
    (void) my_write(fd,(uchar*) buffer->ptr(),buffer->length(),MYF(MY_WME));
3625
 
  (void) my_close(fd,MYF(0));
3626
 
 
3627
 
  if (!(editor = (char *)getenv("EDITOR")) &&
3628
 
      !(editor = (char *)getenv("VISUAL")))
3629
 
    editor = "vi";
3630
 
  strxmov(buff,editor," ",filename,NullS);
3631
 
  (void) system(buff);
3632
 
 
3633
 
  struct stat stat_arg;
3634
 
  if (stat(filename,&stat_arg))
3635
 
    goto err;
3636
 
  if ((fd = my_open(filename,O_RDONLY, MYF(MY_WME))) < 0)
3637
 
    goto err;
3638
 
  (void) buffer->alloc((uint) stat_arg.st_size);
3639
 
  if ((tmp=read(fd,(char*) buffer->ptr(),buffer->alloced_length())) >= 0L)
3640
 
    buffer->length((uint) tmp);
3641
 
  else
3642
 
    buffer->length(0);
3643
 
  (void) my_close(fd,MYF(0));
3644
 
  (void) my_delete(filename,MYF(MY_WME));
3645
 
err:
3646
 
  return 0;
3647
 
}
3648
 
#endif
3649
 
 
3650
3577
 
3651
3578
/* If arg is given, exit without errors. This happens on command 'quit' */
3652
3579
 
3653
3580
static int
3654
 
com_quit(String *buffer __attribute__((unused)),
3655
 
         char *line __attribute__((unused)))
 
3581
com_quit(GString *buffer __attribute__((unused)),
 
3582
         char *line __attribute__((unused)))
3656
3583
{
3657
3584
  /* let the screen auto close on a normal shutdown */
3658
3585
  status.exit_status=0;
3660
3587
}
3661
3588
 
3662
3589
static int
3663
 
com_rehash(String *buffer __attribute__((unused)),
3664
 
         char *line __attribute__((unused)))
 
3590
com_rehash(GString *buffer __attribute__((unused)),
 
3591
           char *line __attribute__((unused)))
3665
3592
{
3666
 
#ifdef HAVE_READLINE
3667
3593
  build_completion_hash(1, 0);
3668
 
#endif
3669
 
  return 0;
3670
 
}
3671
 
 
3672
 
 
3673
 
#ifdef USE_POPEN
3674
 
static int
3675
 
com_shell(String *buffer, char *line __attribute__((unused)))
3676
 
{
3677
 
  char *shell_cmd;
3678
 
 
3679
 
  /* Skip space from line begin */
3680
 
  while (my_isspace(charset_info, *line))
3681
 
    line++;
3682
 
  if (!(shell_cmd = strchr(line, ' ')))
3683
 
  {
3684
 
    put_info("Usage: \\! shell-command", INFO_ERROR);
3685
 
    return -1;
3686
 
  }
3687
 
  /*
3688
 
    The output of the shell command does not
3689
 
    get directed to the pager or the outfile
3690
 
  */
3691
 
  if (system(shell_cmd) == -1)
3692
 
  {
3693
 
    put_info(strerror(errno), INFO_ERROR, errno);
3694
 
    return -1;
3695
 
  }
3696
 
  return 0;
3697
 
}
3698
 
#endif
3699
 
 
3700
 
 
3701
 
static int
3702
 
com_print(String *buffer,char *line __attribute__((unused)))
 
3594
  return 0;
 
3595
}
 
3596
 
 
3597
 
 
3598
 
 
3599
static int
 
3600
com_print(GString *buffer,char *line __attribute__((unused)))
3703
3601
{
3704
3602
  tee_puts("--------------", stdout);
3705
 
  (void) tee_fputs(buffer->c_ptr(), stdout);
3706
 
  if (!buffer->length() || (*buffer)[buffer->length()-1] != '\n')
 
3603
  (void) tee_fputs(buffer->str, stdout);
 
3604
  if ( (buffer->len == 0)
 
3605
       || (buffer->str)[(buffer->len)-1] != '\n')
3707
3606
    tee_putc('\n', stdout);
3708
3607
  tee_puts("--------------\n", stdout);
3709
 
  return 0;                                     /* If empty buffer */
 
3608
  /* If empty buffer */
 
3609
  return 0;
3710
3610
}
3711
3611
 
3712
 
        /* ARGSUSED */
 
3612
/* ARGSUSED */
3713
3613
static int
3714
 
com_connect(String *buffer, char *line)
 
3614
com_connect(GString *buffer, char *line)
3715
3615
{
3716
3616
  char *tmp, buff[256];
3717
3617
  bool save_rehash= opt_rehash;
3732
3632
    if (tmp && *tmp)
3733
3633
    {
3734
3634
      my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
3735
 
      current_db= my_strdup(tmp, MYF(MY_WME));
 
3635
      current_db= g_strdup(tmp);
3736
3636
      tmp= get_arg(buff, 1);
3737
3637
      if (tmp)
3738
3638
      {
3739
 
        my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
3740
 
        current_host=my_strdup(tmp,MYF(MY_WME));
 
3639
        my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
 
3640
        current_host=g_strdup(tmp);
3741
3641
      }
3742
3642
    }
3743
3643
    else
3745
3645
      /* Quick re-connect */
3746
3646
      opt_rehash= 0;                            /* purecov: tested */
3747
3647
    }
3748
 
    buffer->length(0);                          // command used
 
3648
    // command used
 
3649
    assert(buffer!=NULL);
 
3650
    g_string_truncate(buffer, 0);
3749
3651
  }
3750
3652
  else
3751
3653
    opt_rehash= 0;
3755
3657
  if (connected)
3756
3658
  {
3757
3659
    sprintf(buff,"Connection id:    %u",mysql_thread_id(&mysql));
3758
 
    put_info(buff,INFO_INFO);
 
3660
    put_info(buff,INFO_INFO,0,0);
3759
3661
    sprintf(buff,"Current database: %.128s\n",
3760
 
            current_db ? current_db : "*** NONE ***");
3761
 
    put_info(buff,INFO_INFO);
 
3662
            current_db ? current_db : "*** NONE ***");
 
3663
    put_info(buff,INFO_INFO,0,0);
3762
3664
  }
3763
3665
  return error;
3764
3666
}
3765
3667
 
3766
3668
 
3767
 
static int com_source(String *buffer __attribute__((__unused__)), char *line)
 
3669
static int com_source(GString *buffer __attribute__((__unused__)), char *line)
3768
3670
{
3769
3671
  char source_name[FN_REFLEN], *end, *param;
3770
3672
  LINE_BUFFER *line_buff;
3776
3678
  while (my_isspace(charset_info,*line))
3777
3679
    line++;
3778
3680
  if (!(param = strchr(line, ' ')))             // Skip command name
3779
 
    return put_info("Usage: \\. <filename> | source <filename>", 
3780
 
                    INFO_ERROR, 0);
 
3681
    return put_info("Usage: \\. <filename> | source <filename>",
 
3682
                    INFO_ERROR, 0,0);
3781
3683
  while (my_isspace(charset_info,*param))
3782
3684
    param++;
3783
3685
  end=strmake(source_name,param,sizeof(source_name)-1);
3784
 
  while (end > source_name && (my_isspace(charset_info,end[-1]) || 
 
3686
  while (end > source_name && (my_isspace(charset_info,end[-1]) ||
3785
3687
                               my_iscntrl(charset_info,end[-1])))
3786
3688
    end--;
3787
3689
  end[0]=0;
3791
3693
  {
3792
3694
    char buff[FN_REFLEN+60];
3793
3695
    sprintf(buff,"Failed to open file '%s', error: %d", source_name,errno);
3794
 
    return put_info(buff, INFO_ERROR, 0);
 
3696
    return put_info(buff, INFO_ERROR, 0 ,0);
3795
3697
  }
3796
3698
 
3797
3699
  if (!(line_buff=batch_readline_init(opt_max_allowed_packet+512,sql_file)))
3798
3700
  {
3799
3701
    my_fclose(sql_file,MYF(0));
3800
 
    return put_info("Can't initialize batch_readline", INFO_ERROR, 0);
 
3702
    return put_info("Can't initialize batch_readline", INFO_ERROR, 0 ,0);
3801
3703
  }
3802
3704
 
3803
3705
  /* Save old status */
3804
3706
  old_status=status;
3805
3707
  bfill((char*) &status,sizeof(status),(char) 0);
3806
3708
 
3807
 
  status.batch=old_status.batch;                // Run in batch mode
 
3709
  // Run in batch mode
 
3710
  status.batch=old_status.batch;
3808
3711
  status.line_buff=line_buff;
3809
3712
  status.file_name=source_name;
3810
 
  glob_buffer.length(0);                        // Empty command buffer
 
3713
  // Empty command buffer
 
3714
  assert(glob_buffer!=NULL);
 
3715
  g_string_truncate(glob_buffer, 0);
3811
3716
  error= read_and_execute(false);
3812
 
  status=old_status;                            // Continue as before
 
3717
  // Continue as before
 
3718
  status=old_status;
3813
3719
  my_fclose(sql_file,MYF(0));
3814
3720
  batch_readline_end(line_buff);
3815
3721
  return error;
3816
3722
}
3817
3723
 
3818
3724
 
3819
 
        /* ARGSUSED */
 
3725
/* ARGSUSED */
3820
3726
static int
3821
 
com_delimiter(String *buffer __attribute__((unused)), char *line)
 
3727
com_delimiter(GString *buffer __attribute__((unused)), char *line)
3822
3728
{
3823
3729
  char buff[256], *tmp;
3824
3730
 
3828
3734
  if (!tmp || !*tmp)
3829
3735
  {
3830
3736
    put_info("DELIMITER must be followed by a 'delimiter' character or string",
3831
 
             INFO_ERROR);
 
3737
             INFO_ERROR, 0, 0);
3832
3738
    return 0;
3833
3739
  }
3834
3740
  else
3835
3741
  {
3836
 
    if (strstr(tmp, "\\")) 
 
3742
    if (strstr(tmp, "\\"))
3837
3743
    {
3838
 
      put_info("DELIMITER cannot contain a backslash character", INFO_ERROR);
 
3744
      put_info("DELIMITER cannot contain a backslash character",
 
3745
               INFO_ERROR, 0, 0);
3839
3746
      return 0;
3840
3747
    }
3841
3748
  }
3845
3752
  return 0;
3846
3753
}
3847
3754
 
3848
 
        /* ARGSUSED */
 
3755
/* ARGSUSED */
3849
3756
static int
3850
 
com_use(String *buffer __attribute__((unused)), char *line)
 
3757
com_use(GString *buffer __attribute__((unused)), char *line)
3851
3758
{
3852
3759
  char *tmp, buff[FN_REFLEN + 1];
3853
3760
  int select_db;
3857
3764
  tmp= get_arg(buff, 0);
3858
3765
  if (!tmp || !*tmp)
3859
3766
  {
3860
 
    put_info("USE must be followed by a database name", INFO_ERROR);
 
3767
    put_info("USE must be followed by a database name", INFO_ERROR, 0, 0);
3861
3768
    return 0;
3862
3769
  }
3863
3770
  /*
3909
3816
        return put_error(&mysql);
3910
3817
    }
3911
3818
    my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
3912
 
    current_db=my_strdup(tmp,MYF(MY_WME));
3913
 
#ifdef HAVE_READLINE
 
3819
    current_db=g_strdup(tmp);
3914
3820
    if (select_db > 1)
3915
3821
      build_completion_hash(opt_rehash, 1);
3916
 
#endif
3917
3822
  }
3918
3823
 
3919
 
  put_info("Database changed",INFO_INFO);
 
3824
  put_info("Database changed",INFO_INFO, 0, 0);
3920
3825
  return 0;
3921
3826
}
3922
3827
 
3923
3828
static int
3924
 
com_warnings(String *buffer __attribute__((unused)),
3925
 
   char *line __attribute__((unused)))
 
3829
com_warnings(GString *buffer __attribute__((unused)),
 
3830
             char *line __attribute__((unused)))
3926
3831
{
3927
3832
  show_warnings = 1;
3928
 
  put_info("Show warnings enabled.",INFO_INFO);
 
3833
  put_info("Show warnings enabled.",INFO_INFO, 0, 0);
3929
3834
  return 0;
3930
3835
}
3931
3836
 
3932
3837
static int
3933
 
com_nowarnings(String *buffer __attribute__((unused)),
3934
 
   char *line __attribute__((unused)))
 
3838
com_nowarnings(GString *buffer __attribute__((unused)),
 
3839
               char *line __attribute__((unused)))
3935
3840
{
3936
3841
  show_warnings = 0;
3937
 
  put_info("Show warnings disabled.",INFO_INFO);
 
3842
  put_info("Show warnings disabled.",INFO_INFO, 0, 0);
3938
3843
  return 0;
3939
3844
}
3940
3845
 
4002
3907
 
4003
3908
static int
4004
3909
sql_real_connect(char *host,char *database,char *user,char *password,
4005
 
                 uint silent)
 
3910
                 uint silent)
4006
3911
{
4007
3912
  if (connected)
4008
3913
  {
4014
3919
  {
4015
3920
    uint timeout=opt_connect_timeout;
4016
3921
    mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT,
4017
 
                  (char*) &timeout);
 
3922
                  (char*) &timeout);
4018
3923
  }
4019
3924
  if (opt_compress)
4020
3925
    mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
4028
3933
  {
4029
3934
    char init_command[100];
4030
3935
    sprintf(init_command,
4031
 
            "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%"PRIu32
 
3936
                  "SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=%"PRIu32
4032
3937
            ",SQL_MAX_JOIN_SIZE=%"PRIu32,
4033
 
            select_limit, max_join_size);
 
3938
                  select_limit, max_join_size);
4034
3939
    mysql_options(&mysql, MYSQL_INIT_COMMAND, init_command);
4035
3940
  }
4036
3941
  if (default_charset_used)
4037
3942
    mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
4038
3943
  if (!mysql_real_connect(&mysql, host, user, password,
4039
 
                          database, opt_mysql_port, opt_mysql_unix_port,
4040
 
                          connect_flag | CLIENT_MULTI_STATEMENTS))
 
3944
                          database, opt_mysql_port, opt_mysql_unix_port,
 
3945
                          connect_flag | CLIENT_MULTI_STATEMENTS))
4041
3946
  {
4042
3947
    if (!silent ||
4043
 
        (mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
4044
 
         mysql_errno(&mysql) != CR_CONNECTION_ERROR))
 
3948
        (mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
 
3949
         mysql_errno(&mysql) != CR_CONNECTION_ERROR))
4045
3950
    {
4046
3951
      (void) put_error(&mysql);
4047
3952
      (void) fflush(stdout);
4050
3955
    return -1;                                  // Retryable
4051
3956
  }
4052
3957
  connected=1;
4053
 
#ifndef EMBEDDED_LIBRARY
4054
3958
  mysql.reconnect= debug_info_flag; // We want to know if this happens
4055
 
#else
4056
 
  mysql.reconnect= 1;
4057
 
#endif
4058
 
#ifdef HAVE_READLINE
4059
3959
  build_completion_hash(opt_rehash, 1);
4060
 
#endif
4061
3960
  return 0;
4062
3961
}
4063
3962
 
4074
3973
    {
4075
3974
      if (count)
4076
3975
      {
4077
 
        tee_fputs("\n", stderr);
4078
 
        (void) fflush(stderr);
 
3976
        tee_fputs("\n", stderr);
 
3977
        (void) fflush(stderr);
4079
3978
      }
4080
3979
      return error;
4081
3980
    }
4098
3997
 
4099
3998
 
4100
3999
static int
4101
 
com_status(String *buffer __attribute__((unused)),
4102
 
           char *line __attribute__((unused)))
 
4000
com_status(GString *buffer __attribute__((unused)),
 
4001
           char *line __attribute__((unused)))
4103
4002
{
4104
4003
  const char *status_str;
4105
4004
  char buff[40];
4111
4010
  if (connected)
4112
4011
  {
4113
4012
    tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",mysql_thread_id(&mysql));
4114
 
    /* 
4115
 
      Don't remove "limit 1", 
 
4013
    /*
 
4014
      Don't remove "limit 1",
4116
4015
      it is protection againts SQL_SELECT_LIMIT=0
4117
4016
    */
4118
4017
    if (!mysql_query(&mysql,"select DATABASE(), USER() limit 1") &&
4119
 
        (result=mysql_use_result(&mysql)))
 
4018
        (result=mysql_use_result(&mysql)))
4120
4019
    {
4121
4020
      MYSQL_ROW cur=mysql_fetch_row(result);
4122
4021
      if (cur)
4125
4024
        tee_fprintf(stdout, "Current user:\t\t%s\n", cur[1]);
4126
4025
      }
4127
4026
      mysql_free_result(result);
4128
 
    } 
4129
 
      tee_puts("SSL:\t\t\tNot in use", stdout);
 
4027
    }
 
4028
    tee_puts("SSL:\t\t\tNot in use", stdout);
4130
4029
  }
4131
4030
  else
4132
4031
  {
4141
4040
    tee_fprintf(stdout, "\nAll updates ignored to this database\n");
4142
4041
    vidattr(A_NORMAL);
4143
4042
  }
4144
 
#ifdef USE_POPEN
4145
4043
  tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
4146
4044
  tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
4147
 
#endif
4148
4045
  tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
4149
4046
  tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&mysql));
4150
4047
  tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
4205
4102
    vidattr(A_NORMAL);
4206
4103
    tee_fprintf(stdout, "\
4207
4104
UPDATEs and DELETEs that don't use a key in the WHERE clause are not allowed.\n\
4208
 
(One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n\
4209
 
SELECT has an automatic 'LIMIT %lu' if LIMIT is not used.\n\
 
4105
(One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n \
 
4106
SELECT has an automatic 'LIMIT %lu' if LIMIT is not used.\n             \
4210
4107
Max number of examined row combination in a join is set to: %lu\n\n",
4211
 
select_limit, max_join_size);
 
4108
                select_limit, max_join_size);
4212
4109
  }
4213
4110
  tee_puts("--------------\n", stdout);
4214
4111
  return 0;
4261
4158
      fprintf(file,"ERROR");
4262
4159
      if (error)
4263
4160
      {
4264
 
        if (sqlstate)
4265
 
          (void) fprintf(file," %d (%s)",error, sqlstate);
 
4161
        if (sqlstate)
 
4162
          (void) fprintf(file," %d (%s)",error, sqlstate);
4266
4163
        else
4267
 
          (void) fprintf(file," %d",error);
 
4164
          (void) fprintf(file," %d",error);
4268
4165
      }
4269
4166
      if (status.query_start_line && line_numbers)
4270
4167
      {
4271
 
        (void) fprintf(file," at line %"PRIu32,status.query_start_line);
4272
 
        if (status.file_name)
4273
 
          (void) fprintf(file," in file: '%s'", status.file_name);
 
4168
        (void) fprintf(file," at line %"PRIu32,status.query_start_line);
 
4169
        if (status.file_name)
 
4170
          (void) fprintf(file," in file: '%s'", status.file_name);
4274
4171
      }
4275
4172
      (void) fprintf(file,": %s\n",str);
4276
4173
      (void) fflush(file);
4277
4174
      if (!ignore_errors)
4278
 
        return 1;
 
4175
        return 1;
4279
4176
    }
4280
4177
    else if (info_type == INFO_RESULT && verbose > 1)
4281
4178
      tee_puts(str, file);
4295
4192
    if (info_type == INFO_ERROR)
4296
4193
    {
4297
4194
      if (!opt_nobeep)
4298
 
        putchar('\a');                  /* This should make a bell */
 
4195
        /* This should make a bell */
 
4196
        putchar('\a');
4299
4197
      vidattr(A_STANDOUT);
4300
4198
      if (error)
4301
4199
      {
4302
 
        if (sqlstate)
 
4200
        if (sqlstate)
4303
4201
          (void) tee_fprintf(file, "ERROR %d (%s): ", error, sqlstate);
4304
4202
        else
4305
4203
          (void) tee_fprintf(file, "ERROR %d: ", error);
4322
4220
put_error(MYSQL *con)
4323
4221
{
4324
4222
  return put_info(mysql_error(con), INFO_ERROR, mysql_errno(con),
4325
 
                  mysql_sqlstate(con));
4326
 
}  
4327
 
 
4328
 
 
4329
 
static void remove_cntrl(String &buffer)
 
4223
                  mysql_sqlstate(con));
 
4224
}
 
4225
 
 
4226
 
 
4227
static void remove_cntrl(GString *buffer)
4330
4228
{
4331
 
  char *start,*end;
4332
 
  end=(start=(char*) buffer.ptr())+buffer.length();
 
4229
  char *start=  buffer->str;
 
4230
  char *end= start + (buffer->len);
4333
4231
  while (start < end && !my_isgraph(charset_info,end[-1]))
4334
4232
    end--;
4335
 
  buffer.length((uint) (end-start));
 
4233
  uint chars_to_truncate = end-start;
 
4234
  if (buffer->len > chars_to_truncate)
 
4235
    g_string_truncate(buffer, chars_to_truncate);
4336
4236
}
4337
4237
 
4338
4238
 
4392
4292
}
4393
4293
 
4394
4294
 
4395
 
/** 
4396
 
  Write as many as 52+1 bytes to buff, in the form of a legible duration of time.
 
4295
/**
 
4296
   Write as many as 52+1 bytes to buff, in the form of a legible duration of time.
4397
4297
 
4398
 
  len("4294967296 days, 23 hours, 59 minutes, 60.00 seconds")  ->  52
 
4298
   len("4294967296 days, 23 hours, 59 minutes, 60.00 seconds")  ->  52
4399
4299
*/
4400
4300
static void nice_time(double sec,char *buff,bool part_second)
4401
4301
{
4431
4331
static void end_timer(ulong start_time,char *buff)
4432
4332
{
4433
4333
  nice_time((double) (start_timer() - start_time) /
4434
 
            CLOCKS_PER_SEC,buff,1);
 
4334
            CLOCKS_PER_SEC,buff,1);
4435
4335
}
4436
4336
 
4437
4337
 
4443
4343
  strmov(strend(buff),")");
4444
4344
}
4445
4345
 
4446
 
static const char* construct_prompt()
 
4346
static const char * construct_prompt()
4447
4347
{
4448
 
  processed_prompt.free();                      // Erase the old prompt
4449
 
  time_t  lclock = time(NULL);                  // Get the date struct
 
4348
  // Erase the old prompt
 
4349
  assert(processed_prompt!=NULL);
 
4350
  g_string_truncate(processed_prompt, 0);
 
4351
 
 
4352
  // Get the date struct
 
4353
  time_t  lclock = time(NULL);
4450
4354
  struct tm *t = localtime(&lclock);
4451
4355
 
4452
4356
  /* parse thru the settings for the prompt */
4453
 
  for (char *c = current_prompt; *c ; *c++)
 
4357
  for (char *c= current_prompt; *c; (void)*c++)
4454
4358
  {
4455
4359
    if (*c != PROMPT_CHAR)
4456
 
        processed_prompt.append(*c);
 
4360
    {
 
4361
      g_string_append_c(processed_prompt, c[0]);
 
4362
    }
4457
4363
    else
4458
4364
    {
 
4365
      int getHour;
 
4366
      int getYear;
 
4367
      char* dateTime= NULL;
4459
4368
      switch (*++c) {
4460
4369
      case '\0':
4461
 
        c--;                    // stop it from going beyond if ends with %
4462
 
        break;
 
4370
        // stop it from going beyond if ends with %
 
4371
        c--;
 
4372
        break;
4463
4373
      case 'c':
4464
 
        add_int_to_prompt(++prompt_counter);
4465
 
        break;
 
4374
        add_int_to_prompt(++prompt_counter);
 
4375
        break;
4466
4376
      case 'v':
4467
 
        if (connected)
4468
 
          processed_prompt.append(mysql_get_server_info(&mysql));
4469
 
        else
4470
 
          processed_prompt.append("not_connected");
4471
 
        break;
 
4377
        if (connected)
 
4378
          g_string_append(processed_prompt, mysql_get_server_info(&mysql));
 
4379
        else
 
4380
          g_string_append(processed_prompt, "not_connected");
 
4381
        break;
4472
4382
      case 'd':
4473
 
        processed_prompt.append(current_db ? current_db : "(none)");
4474
 
        break;
 
4383
        g_string_append(processed_prompt, current_db ? current_db : "(none)");
 
4384
        break;
4475
4385
      case 'h':
4476
4386
      {
4477
 
        const char *prompt;
4478
 
        prompt= connected ? mysql_get_host_info(&mysql) : "not_connected";
4479
 
        if (strstr(prompt, "Localhost"))
4480
 
          processed_prompt.append("localhost");
4481
 
        else
4482
 
        {
4483
 
          const char *end=strcend(prompt,' ');
4484
 
          processed_prompt.append(prompt, (uint) (end-prompt));
4485
 
        }
4486
 
        break;
 
4387
        const char *prompt;
 
4388
        prompt= connected ? mysql_get_host_info(&mysql) : "not_connected";
 
4389
        if (strstr(prompt, "Localhost"))
 
4390
          g_string_append(processed_prompt, "localhost");
 
4391
        else
 
4392
        {
 
4393
          const char *end=strcend(prompt,' ');
 
4394
          g_string_append_len(processed_prompt, prompt, (gssize) (end-prompt));
 
4395
        }
 
4396
        break;
4487
4397
      }
4488
4398
      case 'p':
4489
4399
      {
4490
 
#ifndef EMBEDDED_LIBRARY
4491
 
        if (!connected)
4492
 
        {
4493
 
          processed_prompt.append("not_connected");
4494
 
          break;
4495
 
        }
 
4400
        if (!connected)
 
4401
        {
 
4402
          g_string_append(processed_prompt, "not_connected");
 
4403
          break;
 
4404
        }
4496
4405
 
4497
 
        const char *host_info = mysql_get_host_info(&mysql);
4498
 
        if (strstr(host_info, "memory")) 
4499
 
        {
4500
 
                processed_prompt.append( mysql.host );
4501
 
        }
4502
 
        else if (strstr(host_info,"TCP/IP") ||
4503
 
            !mysql.unix_socket)
4504
 
          add_int_to_prompt(mysql.port);
4505
 
        else
4506
 
        {
4507
 
          char *pos=strrchr(mysql.unix_socket,'/');
4508
 
          processed_prompt.append(pos ? pos+1 : mysql.unix_socket);
4509
 
        }
4510
 
#endif
 
4406
        const char *host_info = mysql_get_host_info(&mysql);
 
4407
        if (strstr(host_info, "memory"))
 
4408
        {
 
4409
          g_string_append(processed_prompt, mysql.host );
 
4410
        }
 
4411
        else if (strstr(host_info,"TCP/IP") ||
 
4412
                 !mysql.unix_socket)
 
4413
          add_int_to_prompt(mysql.port);
 
4414
        else
 
4415
        {
 
4416
          char *pos=strrchr(mysql.unix_socket,'/');
 
4417
          g_string_append(processed_prompt, pos ? pos+1 : mysql.unix_socket);
 
4418
        }
4511
4419
      }
4512
 
        break;
 
4420
      break;
4513
4421
      case 'U':
4514
 
        if (!full_username)
4515
 
          init_username();
4516
 
        processed_prompt.append(full_username ? full_username :
4517
 
                                (current_user ?  current_user : "(unknown)"));
4518
 
        break;
 
4422
        if (!full_username)
 
4423
          init_username();
 
4424
        g_string_append(processed_prompt, full_username ? full_username :
 
4425
                        (current_user ?  current_user : "(unknown)"));
 
4426
        break;
4519
4427
      case 'u':
4520
 
        if (!full_username)
4521
 
          init_username();
4522
 
        processed_prompt.append(part_username ? part_username :
4523
 
                                (current_user ?  current_user : "(unknown)"));
4524
 
        break;
 
4428
        if (!full_username)
 
4429
          init_username();
 
4430
        g_string_append(processed_prompt, part_username ? part_username :
 
4431
                        (current_user ?  current_user : "(unknown)"));
 
4432
        break;
4525
4433
      case PROMPT_CHAR:
4526
 
        processed_prompt.append(PROMPT_CHAR);
4527
 
        break;
 
4434
        g_string_append_c(processed_prompt, PROMPT_CHAR);
 
4435
        break;
4528
4436
      case 'n':
4529
 
        processed_prompt.append('\n');
4530
 
        break;
 
4437
        g_string_append_c(processed_prompt, '\n');
 
4438
        break;
4531
4439
      case ' ':
4532
4440
      case '_':
4533
 
        processed_prompt.append(' ');
4534
 
        break;
 
4441
        g_string_append_c(processed_prompt, ' ');
 
4442
        break;
4535
4443
      case 'R':
4536
 
        if (t->tm_hour < 10)
4537
 
          processed_prompt.append('0');
4538
 
        add_int_to_prompt(t->tm_hour);
4539
 
        break;
 
4444
        if (t->tm_hour < 10)
 
4445
          g_string_append_c(processed_prompt, '0');
 
4446
        add_int_to_prompt(t->tm_hour);
 
4447
        break;
4540
4448
      case 'r':
4541
 
        int getHour;
4542
 
        getHour = t->tm_hour % 12;
4543
 
        if (getHour == 0)
4544
 
          getHour=12;
4545
 
        if (getHour < 10)
4546
 
          processed_prompt.append('0');
4547
 
        add_int_to_prompt(getHour);
4548
 
        break;
 
4449
        getHour = t->tm_hour % 12;
 
4450
        if (getHour == 0)
 
4451
          getHour=12;
 
4452
        if (getHour < 10)
 
4453
          g_string_append_c(processed_prompt, '0');
 
4454
        add_int_to_prompt(getHour);
 
4455
        break;
4549
4456
      case 'm':
4550
 
        if (t->tm_min < 10)
4551
 
          processed_prompt.append('0');
4552
 
        add_int_to_prompt(t->tm_min);
4553
 
        break;
 
4457
        if (t->tm_min < 10)
 
4458
          g_string_append_c(processed_prompt, '0');
 
4459
        add_int_to_prompt(t->tm_min);
 
4460
        break;
4554
4461
      case 'y':
4555
 
        int getYear;
4556
 
        getYear = t->tm_year % 100;
4557
 
        if (getYear < 10)
4558
 
          processed_prompt.append('0');
4559
 
        add_int_to_prompt(getYear);
4560
 
        break;
 
4462
        getYear = t->tm_year % 100;
 
4463
        if (getYear < 10)
 
4464
          g_string_append_c(processed_prompt, '0');
 
4465
        add_int_to_prompt(getYear);
 
4466
        break;
4561
4467
      case 'Y':
4562
 
        add_int_to_prompt(t->tm_year+1900);
4563
 
        break;
 
4468
        add_int_to_prompt(t->tm_year+1900);
 
4469
        break;
4564
4470
      case 'D':
4565
 
        char* dateTime;
4566
 
        dateTime = ctime(&lclock);
4567
 
        processed_prompt.append(strtok(dateTime,"\n"));
4568
 
        break;
 
4471
        dateTime = ctime(&lclock);
 
4472
        g_string_append(processed_prompt, strtok(dateTime,"\n"));
 
4473
        break;
4569
4474
      case 's':
4570
 
        if (t->tm_sec < 10)
4571
 
          processed_prompt.append('0');
4572
 
        add_int_to_prompt(t->tm_sec);
4573
 
        break;
 
4475
        if (t->tm_sec < 10)
 
4476
          g_string_append_c(processed_prompt, '0');
 
4477
        add_int_to_prompt(t->tm_sec);
 
4478
        break;
4574
4479
      case 'w':
4575
 
        processed_prompt.append(day_names[t->tm_wday]);
4576
 
        break;
 
4480
        g_string_append(processed_prompt, (day_names[t->tm_wday]));
 
4481
        break;
4577
4482
      case 'P':
4578
 
        processed_prompt.append(t->tm_hour < 12 ? "am" : "pm");
4579
 
        break;
 
4483
        g_string_append(processed_prompt, t->tm_hour < 12 ? "am" : "pm");
 
4484
        break;
4580
4485
      case 'o':
4581
 
        add_int_to_prompt(t->tm_mon+1);
4582
 
        break;
 
4486
        add_int_to_prompt(t->tm_mon+1);
 
4487
        break;
4583
4488
      case 'O':
4584
 
        processed_prompt.append(month_names[t->tm_mon]);
4585
 
        break;
 
4489
        g_string_append(processed_prompt, month_names[t->tm_mon]);
 
4490
        break;
4586
4491
      case '\'':
4587
 
        processed_prompt.append("'");
4588
 
        break;
 
4492
        g_string_append(processed_prompt, "'");
 
4493
        break;
4589
4494
      case '"':
4590
 
        processed_prompt.append('"');
4591
 
        break;
 
4495
        g_string_append_c(processed_prompt, '"');
 
4496
        break;
4592
4497
      case 'S':
4593
 
        processed_prompt.append(';');
4594
 
        break;
 
4498
        g_string_append_c(processed_prompt, ';');
 
4499
        break;
4595
4500
      case 't':
4596
 
        processed_prompt.append('\t');
4597
 
        break;
 
4501
        g_string_append_c(processed_prompt, '\t');
 
4502
        break;
4598
4503
      case 'l':
4599
 
        processed_prompt.append(delimiter_str);
4600
 
        break;
 
4504
        g_string_append(processed_prompt, delimiter_str);
 
4505
        break;
4601
4506
      default:
4602
 
        processed_prompt.append(c);
 
4507
        g_string_append(processed_prompt, c);
4603
4508
      }
4604
4509
    }
4605
4510
  }
4606
 
  processed_prompt.append('\0');
4607
 
  return processed_prompt.ptr();
 
4511
  // TODO: Is this needed with GString?
 
4512
  g_string_append_c(processed_prompt, '\0');
 
4513
  return processed_prompt->str;
4608
4514
}
4609
4515
 
4610
4516
 
4612
4518
{
4613
4519
  char buffer[16];
4614
4520
  int10_to_str(toadd,buffer,10);
4615
 
  processed_prompt.append(buffer);
 
4521
  g_string_append(processed_prompt, buffer);
4616
4522
}
4617
4523
 
4618
4524
static void init_username()
4625
4531
      (result=mysql_use_result(&mysql)))
4626
4532
  {
4627
4533
    MYSQL_ROW cur=mysql_fetch_row(result);
4628
 
    full_username=my_strdup(cur[0],MYF(MY_WME));
4629
 
    part_username=my_strdup(strtok(cur[0],"@"),MYF(MY_WME));
 
4534
    full_username=g_strdup(cur[0]);
 
4535
    part_username=g_strdup(strtok(cur[0],"@"));
4630
4536
    (void) mysql_fetch_row(result);             // Read eof
4631
4537
  }
4632
4538
}
4633
4539
 
4634
 
static int com_prompt(String *buffer __attribute__((__unused__)), char *line)
 
4540
static int com_prompt(GString *buffer __attribute__((__unused__)), char *line)
4635
4541
{
4636
4542
  char *ptr=strchr(line, ' ');
4637
4543
  prompt_counter = 0;
4638
4544
  my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR));
4639
 
  current_prompt=my_strdup(ptr ? ptr+1 : default_prompt,MYF(MY_WME));
 
4545
  current_prompt=g_strdup(ptr ? ptr+1 : default_prompt->str);
4640
4546
  if (!ptr)
4641
 
    tee_fprintf(stdout, "Returning to default PROMPT of %s\n", default_prompt);
 
4547
    tee_fprintf(stdout, "Returning to default PROMPT of %s\n",
 
4548
                default_prompt->str);
4642
4549
  else
4643
4550
    tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
4644
4551
  return 0;
4645
4552
}
4646
 
 
4647
 
#ifndef EMBEDDED_LIBRARY
4648
 
/* Keep sql_string library happy */
4649
 
 
4650
 
void *sql_alloc(size_t Size)
4651
 
{
4652
 
  return my_malloc(Size,MYF(MY_WME));
4653
 
}
4654
 
 
4655
 
void sql_element_free(void *ptr)
4656
 
{
4657
 
  my_free(ptr,MYF(0));
4658
 
}
4659
 
#endif /* EMBEDDED_LIBRARY */