~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysql.cc

  • Committer: Monty Taylor
  • Date: 2008-07-12 14:43:50 UTC
  • mto: (77.6.1 glibclient-merge)
  • mto: This revision was merged to the branch mainline in revision 176.
  • Revision ID: monty@inaugust.com-20080712144350-g1r05g8kciv5np0t
First steps in removing sql_string and using glib instead.

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
43
48
#include <locale.h>
44
49
#endif
45
50
 
 
51
#include <glib/gstring.h>
 
52
 
46
53
const char *VER= "14.14";
47
54
 
48
55
/* Don't try to make a nice table if the data is too big */
56
63
 
57
64
void* sql_alloc(unsigned size);      // Don't use mysqld alloc for these
58
65
void sql_element_free(void *ptr);
59
 
#include "sql_string.h"
60
66
 
61
67
extern "C" {
62
68
#if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
88
94
#undef bcmp                             // Fix problem with new readline
89
95
 
90
96
#include <readline/readline.h>
91
 
#define HAVE_READLINE
92
97
 
93
98
  //int vidattr(long unsigned int attrs);       // Was missing in sun curses
94
99
}
150
155
            *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
151
156
static char *histfile;
152
157
static char *histfile_tmp;
153
 
static String glob_buffer,old_buffer;
154
 
static String processed_prompt;
 
158
static GString *glob_buffer, *old_buffer;
 
159
static GString *processed_prompt;
155
160
static char *full_username=0,*part_username=0,*default_prompt=0;
156
161
static int wait_time = 5;
157
162
static STATUS status;
193
198
static int get_options(int argc,char **argv);
194
199
extern "C" my_bool get_one_option(int optid, const struct my_option *opt,
195
200
                                  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*);
 
201
static int com_quit(GString *str,char*),
 
202
           com_go(GString *str,char*), com_ego(GString *str,char*),
 
203
           com_print(GString *str,char*),
 
204
           com_help(GString *str,char*), com_clear(GString *str,char*),
 
205
           com_connect(GString *str,char*), com_status(GString *str,char*),
 
206
           com_use(GString *str,char*), com_source(GString *str, char*),
 
207
           com_rehash(GString *str, char*), com_tee(GString *str, char*),
 
208
           com_notee(GString *str, char*), com_charset(GString *str,char*),
 
209
           com_prompt(GString *str, char*), com_delimiter(GString *str, char*),
 
210
     com_warnings(GString *str, char*), com_nowarnings(GString *str, char*);
206
211
 
207
212
#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 *);
 
213
static int com_nopager(GString *str, char*), com_pager(GString *str, char*),
 
214
           com_edit(GString *str,char*), com_shell(GString *str, char *);
210
215
#endif
211
216
 
212
217
static int read_and_execute(bool interactive);
231
236
 
232
237
/* A structure which contains information on the commands this program
233
238
   can understand. */
234
 
 
 
239
/* TODO: Why are we doing this crap in a C++ program? */
235
240
typedef struct {
236
241
  const char *name;             /* User printable name of the function. */
237
242
  char cmd_char;                /* msql command character */
238
 
  int (*func)(String *str,char *); /* Function to call to do the job. */
 
243
  int (*func)(GString *str,char *); /* Function to call to do the job. */
239
244
  bool takes_params;            /* Max parameters for command */
240
245
  const char *doc;              /* Documentation for this function.  */
241
246
} COMMANDS;
1000
1005
static const char *embedded_server_groups[]=
1001
1006
{ "server", "embedded", "mysql_SERVER", 0 };
1002
1007
 
1003
 
#ifdef HAVE_READLINE
1004
1008
/*
1005
1009
 HIST_ENTRY is defined for libedit, but not for the real readline
1006
1010
 Need to redefine it for real readline to find it
1019
1023
extern "C" int history_length;
1020
1024
static int not_in_history(const char *line);
1021
1025
static void initialize_readline (char *name);
1022
 
static void fix_history(String *final_command);
1023
 
#endif
 
1026
static void fix_history(GString *final_command);
1024
1027
 
1025
1028
static COMMANDS *find_command(char *name,char cmd_name);
1026
 
static bool add_line(String &buffer,char *line,char *in_string,
 
1029
static bool add_line(GString *buffer,char *line,char *in_string,
1027
1030
                     bool *ml_comment);
1028
 
static void remove_cntrl(String &buffer);
 
1031
static void remove_cntrl(GString *buffer);
1029
1032
static void print_table_data(MYSQL_RES *result);
1030
1033
static void print_table_data_html(MYSQL_RES *result);
1031
1034
static void print_table_data_xml(MYSQL_RES *result);
1049
1052
  MY_INIT(argv[0]);
1050
1053
  DBUG_ENTER("main");
1051
1054
  DBUG_PROCESS(argv[0]);
1052
 
  
 
1055
 
1053
1056
  delimiter_str= delimiter;
1054
1057
  default_prompt = my_strdup(getenv("MYSQL_PS1") ? 
1055
1058
                             getenv("MYSQL_PS1") : 
1113
1116
    my_end(0);
1114
1117
    exit(1);
1115
1118
  }
1116
 
  glob_buffer.realloc(512);
1117
1119
  completion_hash_init(&ht, 128);
1118
1120
  init_alloc_root(&hash_mem_root, 16384, 0);
1119
1121
  bzero((char*) &mysql, sizeof(mysql));
1141
1143
#endif
1142
1144
 
1143
1145
  put_info("Welcome to the Drizzle client..  Commands end with ; or \\g.",
1144
 
           INFO_INFO);
1145
 
  sprintf((char*) glob_buffer.ptr(),
1146
 
          "Your Drizzle connection id is %lu\nServer version: %s\n",
1147
 
          mysql_thread_id(&mysql), server_version_string(&mysql));
1148
 
  put_info((char*) glob_buffer.ptr(),INFO_INFO);
 
1146
           INFO_INFO);
 
1147
  glob_buffer = g_string_sized_new(512);
 
1148
  g_string_printf(glob_buffer,
 
1149
                  "Your Drizzle connection id is %lu\nServer version: %s\n",
 
1150
                  mysql_thread_id(&mysql), server_version_string(&mysql));
 
1151
  put_info(glob_buffer->str,INFO_INFO);
1149
1152
 
1150
 
#ifdef HAVE_READLINE
1151
1153
  initialize_readline((char*) my_progname);
1152
1154
  if (!status.batch && !quick && !opt_html && !opt_xml)
1153
1155
  {
1157
1159
    else if (getenv("HOME"))
1158
1160
    {
1159
1161
      histfile=(char*) my_malloc((uint) strlen(getenv("HOME"))
1160
 
                                 + (uint) strlen("/.mysql_history")+2,
1161
 
                                 MYF(MY_WME));
 
1162
                                 + (uint) strlen("/.mysql_history")+2,
 
1163
                                 MYF(MY_WME));
1162
1164
      if (histfile)
1163
 
        sprintf(histfile,"%s/.mysql_history",getenv("HOME"));
 
1165
        sprintf(histfile,"%s/.mysql_history",getenv("HOME"));
1164
1166
      char link_name[FN_REFLEN];
1165
1167
      if (my_readlink(link_name, histfile, 0) == 0 &&
1166
1168
          strncmp(link_name, "/dev/null", 10) == 0)
1173
1175
    if (histfile)
1174
1176
    {
1175
1177
      if (verbose)
1176
 
        tee_fprintf(stdout, "Reading history-file %s\n",histfile);
 
1178
        tee_fprintf(stdout, "Reading history-file %s\n",histfile);
1177
1179
      read_history(histfile);
1178
1180
      if (!(histfile_tmp= (char*) my_malloc((uint) strlen(histfile) + 5,
1179
 
                                            MYF(MY_WME))))
 
1181
                                            MYF(MY_WME))))
1180
1182
      {
1181
 
        fprintf(stderr, "Couldn't allocate memory for temp histfile!\n");
1182
 
        exit(1);
 
1183
        fprintf(stderr, "Couldn't allocate memory for temp histfile!\n");
 
1184
        exit(1);
1183
1185
      }
1184
1186
      sprintf(histfile_tmp, "%s.TMP", histfile);
1185
1187
    }
1186
1188
  }
1187
 
#endif
1188
1189
  sprintf(buff, "%s",
1189
 
#ifndef NOT_YET
1190
 
          "Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n");
1191
 
#else
1192
 
          "Type 'help [[%]function name[%]]' to get help on usage of function.\n");
1193
 
#endif
 
1190
          "Type 'help;' or '\\h' for help. Type '\\c' to clear the buffer.\n");
 
1191
 
1194
1192
  put_info(buff,INFO_INFO);
1195
1193
  status.exit_status= read_and_execute(!status.batch);
1196
1194
  if (opt_outfile)
1197
1195
    end_tee();
1198
1196
  mysql_end(0);
1199
 
#ifndef _lint
1200
 
  DBUG_RETURN(0);                               // Keep compiler happy
1201
 
#endif
 
1197
  return 0;
1202
1198
}
1203
1199
 
1204
1200
sig_handler mysql_end(int sig)
1205
1201
{
1206
1202
  mysql_close(&mysql);
1207
 
#ifdef HAVE_READLINE
1208
1203
  if (!status.batch && !quick && !opt_html && !opt_xml && histfile)
1209
1204
  {
1210
1205
    /* write-history */
1217
1212
  completion_hash_free(&ht);
1218
1213
  free_root(&hash_mem_root,MYF(0));
1219
1214
 
1220
 
#endif
1221
1215
  if (sig >= 0)
1222
1216
    put_info(sig ? "Aborted" : "Bye", INFO_RESULT);
1223
 
  glob_buffer.free();
1224
 
  old_buffer.free();
1225
 
  processed_prompt.free();
 
1217
  g_string_free(glob_buffer,true);
 
1218
  g_string_free(old_buffer,true);
 
1219
  g_string_free(processed_prompt,true);
1226
1220
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
1227
1221
  my_free(opt_mysql_unix_port,MYF(MY_ALLOW_ZERO_PTR));
1228
1222
  my_free(histfile,MYF(MY_ALLOW_ZERO_PTR));
1494
1488
 
1495
1489
static void usage(int version)
1496
1490
{
1497
 
#if defined(USE_LIBEDIT_INTERFACE)
1498
 
  const char* readline= "";
1499
 
#else
1500
1491
  const char* readline= "readline";
1501
 
#endif
1502
1492
 
1503
 
#ifdef HAVE_READLINE
1504
1493
  printf("%s  Ver %s Distrib %s, for %s (%s) using %s %s\n",
1505
 
         my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,
 
1494
         my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE,
1506
1495
         readline, rl_library_version);
1507
 
#else
1508
 
  printf("%s  Ver %s Distrib %s, for %s (%s)\n", my_progname, VER,
1509
 
        MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
1510
 
#endif
1511
1496
 
1512
1497
  if (version)
1513
1498
    return;
1781
1766
           (uchar) line[2] == 0xBF)
1782
1767
        line+= 3;
1783
1768
      line_number++;
1784
 
      if (!glob_buffer.length())
 
1769
      if (!glob_buffer->len)
1785
1770
        status.query_start_line=line_number;
1786
1771
    }
1787
1772
    else
1788
1773
    {
1789
1774
      char *prompt= (char*) (ml_comment ? "   /*> " :
1790
 
                             glob_buffer.is_empty() ?  construct_prompt() :
 
1775
                             (glob_buffer->len == 0) ?  construct_prompt() :
1791
1776
                             !in_string ? "    -> " :
1792
1777
                             in_string == '\'' ?
1793
1778
                             "    '> " : (in_string == '`' ?
1794
1779
                             "    `> " :
1795
1780
                             "    \"> "));
1796
 
      if (opt_outfile && glob_buffer.is_empty())
 
1781
      if (opt_outfile && (glob_buffer->len==0))
1797
1782
        fflush(OUTFILE);
1798
1783
 
1799
1784
      if (opt_outfile)
1805
1790
        which may cause coredump.
1806
1791
      */
1807
1792
      if (opt_outfile && line)
1808
 
        fprintf(OUTFILE, "%s\n", line);
 
1793
        fprintf(OUTFILE, "%s\n", line);
1809
1794
    }
1810
 
    if (!line)                                  // End of file
 
1795
    // End of file
 
1796
    if (!line)
1811
1797
    {
1812
1798
      status.exit_status=0;
1813
1799
      break;
1817
1803
      Check if line is a mysql command line
1818
1804
      (We want to allow help, print and clear anywhere at line start
1819
1805
    */
1820
 
    if ((named_cmds || glob_buffer.is_empty())
1821
 
        && !ml_comment && !in_string && (com=find_command(line,0)))
 
1806
    if ((named_cmds || (glob_buffer->len==0))
 
1807
        && !ml_comment && !in_string && (com=find_command(line,0)))
1822
1808
    {
1823
 
      if ((*com->func)(&glob_buffer,line) > 0)
1824
 
        break;
1825
 
      if (glob_buffer.is_empty())               // If buffer was emptied
1826
 
        in_string=0;
1827
 
#ifdef HAVE_READLINE
 
1809
      if ((*com->func)(glob_buffer,line) > 0)
 
1810
        break;
 
1811
      // If buffer was emptied
 
1812
      if (glob_buffer->len==0)
 
1813
        in_string=0;
1828
1814
      if (interactive && status.add_to_history && not_in_history(line))
1829
 
        add_history(line);
1830
 
#endif
 
1815
        add_history(line);
1831
1816
      continue;
1832
1817
    }
1833
1818
    if (add_line(glob_buffer,line,&in_string,&ml_comment))
1838
1823
  if (!interactive && !status.exit_status)
1839
1824
  {
1840
1825
    remove_cntrl(glob_buffer);
1841
 
    if (!glob_buffer.is_empty())
 
1826
    if (glob_buffer->len > 0)
1842
1827
    {
1843
1828
      status.exit_status=1;
1844
 
      if (com_go(&glob_buffer,line) <= 0)
1845
 
        status.exit_status=0;
 
1829
      if (com_go(glob_buffer,line) <= 0)
 
1830
        status.exit_status=0;
1846
1831
    }
1847
1832
  }
1848
1833
 
1903
1888
}
1904
1889
 
1905
1890
 
1906
 
static bool add_line(String &buffer,char *line,char *in_string,
 
1891
static bool add_line(GString *buffer,char *line,char *in_string,
1907
1892
                     bool *ml_comment)
1908
1893
{
1909
1894
  uchar inchar;
1913
1898
  bool ss_comment= 0;
1914
1899
  DBUG_ENTER("add_line");
1915
1900
 
1916
 
  if (!line[0] && buffer.is_empty())
 
1901
  if (!line[0] && (buffer->len==0))
1917
1902
    DBUG_RETURN(0);
1918
 
#ifdef HAVE_READLINE
1919
1903
  if (status.add_to_history && line[0] && not_in_history(line))
1920
1904
    add_history(line);
1921
 
#endif
1922
1905
  char *end_of_line=line+(uint) strlen(line);
1923
1906
 
1924
1907
  for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
1927
1910
    {
1928
1911
      // Skip spaces at the beggining of a statement
1929
1912
      if (my_isspace(charset_info,inchar) && (out == line) &&
1930
 
          buffer.is_empty())
 
1913
          (buffer->len==0))
1931
1914
        continue;
1932
1915
    }
1933
 
        
 
1916
 
1934
1917
#ifdef USE_MB
1935
1918
    // Accept multi-byte characters as-is
1936
1919
    int length;
1954
1937
      // Found possbile one character command like \c
1955
1938
 
1956
1939
      if (!(inchar = (uchar) *++pos))
1957
 
        break;                          // readline adds one '\'
 
1940
        break;                          // readline adds one '\'
1958
1941
      if (*in_string || inchar == 'N')  // \N is short for NULL
1959
1942
      {                                 // Don't allow commands in string
1960
 
        *out++='\\';
1961
 
        *out++= (char) inchar;
1962
 
        continue;
 
1943
        *out++='\\';
 
1944
        *out++= (char) inchar;
 
1945
        continue;
1963
1946
      }
1964
1947
      if ((com=find_command(NullS,(char) inchar)))
1965
1948
      {
1966
1949
        // Flush previously accepted characters
1967
1950
        if (out != line)
1968
1951
        {
1969
 
          buffer.append(line, (uint) (out-line));
 
1952
          g_string_append_len(buffer, line, (gssize) (out-line));
1970
1953
          out= line;
1971
1954
        }
1972
 
        
1973
 
        if ((*com->func)(&buffer,pos-1) > 0)
 
1955
 
 
1956
        if ((*com->func)(buffer,pos-1) > 0)
1974
1957
          DBUG_RETURN(1);                       // Quit
1975
1958
        if (com->takes_params)
1976
1959
        {
2016
1999
      // Flush previously accepted characters
2017
2000
      if (out != line)
2018
2001
      {
2019
 
        buffer.append(line, (uint32) (out - line));
 
2002
        g_string_append_len(buffer, line, (gssize) (out - line));
2020
2003
        out= line;
2021
2004
      }
2022
2005
 
2023
2006
      // Flush possible comments in the buffer
2024
 
      if (!buffer.is_empty())
 
2007
      if (buffer->len > 0)
2025
2008
      {
2026
 
        if (com_go(&buffer, 0) > 0) // < 0 is not fatal
 
2009
        if (com_go(buffer, 0) > 0) // < 0 is not fatal
2027
2010
          DBUG_RETURN(1);
2028
 
        buffer.length(0);
 
2011
        g_string_truncate(buffer,0);
2029
2012
      }
2030
2013
 
2031
2014
      /*
2032
2015
        Delimiter wants the get rest of the given line as argument to
2033
2016
        allow one to change ';' to ';;' and back
2034
2017
      */
2035
 
      buffer.append(pos);
2036
 
      if (com_delimiter(&buffer, pos) > 0)
 
2018
      g_string_append(buffer,pos);
 
2019
      if (com_delimiter(buffer, pos) > 0)
2037
2020
        DBUG_RETURN(1);
2038
2021
 
2039
 
      buffer.length(0);
 
2022
      g_string_truncate(buffer,0);
2040
2023
      break;
2041
2024
    }
2042
2025
    else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter))
2052
2035
      // Flush previously accepted characters
2053
2036
      if (out != line)
2054
2037
      {
2055
 
        buffer.append(line, (uint32) (out-line));
 
2038
        g_string_append_len(buffer, line, (gssize) (out-line));
2056
2039
        out= line;
2057
2040
      }
2058
2041
 
2062
2045
                                 my_isspace(charset_info, pos[2]))))
2063
2046
      {
2064
2047
        // Add trailing single line comments to this statement
2065
 
        buffer.append(pos);
 
2048
        g_string_append(buffer, pos);
2066
2049
        pos+= strlen(pos);
2067
2050
      }
2068
2051
 
2069
2052
      pos--;
2070
2053
 
2071
 
      if ((com= find_command(buffer.c_ptr(), 0)))
 
2054
      if ((com= find_command(buffer->str, 0)))
2072
2055
      {
2073
2056
          
2074
 
        if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
 
2057
        if ((*com->func)(buffer, buffer->str) > 0)
2075
2058
          DBUG_RETURN(1);                       // Quit 
2076
2059
      }
2077
2060
      else
2078
2061
      {
2079
 
        if (com_go(&buffer, 0) > 0)             // < 0 is not fatal
 
2062
        if (com_go(buffer, 0) > 0)             // < 0 is not fatal
2080
2063
          DBUG_RETURN(1);
2081
2064
      }
2082
 
      buffer.length(0);
 
2065
      g_string_truncate(buffer,0);
2083
2066
    }
2084
 
    else if (!*ml_comment && (!*in_string && (inchar == '#' ||
2085
 
                              (inchar == '-' && pos[1] == '-' && my_isspace(charset_info,pos[2])))))
 
2067
    else if (!*ml_comment
 
2068
             && (!*in_string
 
2069
                 && (inchar == '#'
 
2070
                     || (inchar == '-'
 
2071
                         && pos[1] == '-'
 
2072
                         && my_isspace(charset_info,pos[2])))))
2086
2073
    {
2087
2074
      // Flush previously accepted characters
2088
2075
      if (out != line)
2089
2076
      {
2090
 
        buffer.append(line, (uint32) (out - line));
 
2077
        g_string_append_len(buffer, line, (gssize) (out - line));
2091
2078
        out= line;
2092
2079
      }
2093
2080
 
2094
2081
      // comment to end of line
2095
2082
      if (preserve_comments)
2096
 
        buffer.append(pos);
 
2083
        g_string_append(buffer,pos);
2097
2084
 
2098
2085
      break;
2099
2086
    }
2100
2087
    else if (!*in_string && inchar == '/' && *(pos+1) == '*' &&
2101
 
             *(pos+2) != '!')
 
2088
             *(pos+2) != '!')
2102
2089
    {
2103
2090
      if (preserve_comments)
2104
2091
      {
2110
2097
      *ml_comment= 1;
2111
2098
      if (out != line)
2112
2099
      {
2113
 
        buffer.append(line,(uint) (out-line));
 
2100
        g_string_append_len(buffer, line, (gssize) (out-line));
2114
2101
        out=line;
2115
2102
      }
2116
2103
    }
2126
2113
      *ml_comment= 0;
2127
2114
      if (out != line)
2128
2115
      {
2129
 
        buffer.append(line, (uint32) (out - line));
 
2116
        g_string_append_len(buffer, line, (gssize) (out - line));
2130
2117
        out= line;
2131
2118
      }
2132
2119
      // Consumed a 2 chars or more, and will add 1 at most,
2133
2120
      // so using the 'line' buffer to edit data in place is ok.
2134
2121
      need_space= 1;
2135
 
    }      
 
2122
    }
2136
2123
    else
2137
 
    {                                           // Add found char to buffer
 
2124
    {
 
2125
      // Add found char to buffer
2138
2126
      if (!*in_string && inchar == '/' && *(pos + 1) == '*' &&
2139
2127
          *(pos + 2) == '!')
2140
2128
        ss_comment= 1;
2141
2129
      else if (!*in_string && ss_comment && inchar == '*' && *(pos + 1) == '/')
2142
2130
        ss_comment= 0;
2143
2131
      if (inchar == *in_string)
2144
 
        *in_string= 0;
 
2132
        *in_string= 0;
2145
2133
      else if (!*ml_comment && !*in_string &&
2146
 
               (inchar == '\'' || inchar == '"' || inchar == '`'))
2147
 
        *in_string= (char) inchar;
 
2134
               (inchar == '\'' || inchar == '"' || inchar == '`'))
 
2135
        *in_string= (char) inchar;
2148
2136
      if (!*ml_comment || preserve_comments)
2149
2137
      {
2150
2138
        if (need_space && !my_isspace(charset_info, (char)inchar))
2154
2142
      }
2155
2143
    }
2156
2144
  }
2157
 
  if (out != line || !buffer.is_empty())
 
2145
  if (out != line || (buffer->len > 0))
2158
2146
  {
2159
2147
    *out++='\n';
2160
2148
    uint length=(uint) (out-line);
2161
 
    if (buffer.length() + length >= buffer.alloced_length())
2162
 
      buffer.realloc(buffer.length()+length+IO_SIZE);
2163
 
    if ((!*ml_comment || preserve_comments) && buffer.append(line, length))
 
2149
    if ((!*ml_comment || preserve_comments)
 
2150
        || (g_string_append_len(buffer, line, length)==NULL))
2164
2151
      DBUG_RETURN(1);
2165
2152
  }
2166
2153
  DBUG_RETURN(0);
2170
2157
            Interface to Readline Completion
2171
2158
******************************************************************/
2172
2159
 
2173
 
#ifdef HAVE_READLINE
2174
2160
 
2175
2161
static char *new_command_generator(const char *text, int);
2176
2162
extern "C" char **new_mysql_completion (const char *text, int start, int end);
2187
2173
extern "C" char *no_completion()
2188
2174
#endif
2189
2175
{
2190
 
  return 0;                                     /* No filename completion */
 
2176
  /* No filename completion */
 
2177
  return 0;
2191
2178
}
2192
2179
 
2193
 
/*      glues pieces of history back together if in pieces   */
2194
 
static void fix_history(String *final_command) 
 
2180
/* glues pieces of history back together if in pieces   */
 
2181
static void fix_history(GString *final_command)
2195
2182
{
2196
2183
  int total_lines = 1;
2197
 
  char *ptr = final_command->c_ptr();
2198
 
  String fixed_buffer;  /* Converted buffer */
 
2184
  const char *ptr = final_command->str;
 
2185
  /* Converted buffer */
 
2186
  GString * fixed_buffer;
 
2187
  fixed_buffer = g_string_sized_new(16);
2199
2188
  char str_char = '\0';  /* Character if we are in a string or not */
2200
 
  
 
2189
 
2201
2190
  /* find out how many lines we have and remove newlines */
2202
 
  while (*ptr != '\0') 
 
2191
  while (*ptr != '\0')
2203
2192
  {
2204
2193
    switch (*ptr) {
2205
2194
      /* string character */
2206
2195
    case '"':
2207
2196
    case '\'':
2208
2197
    case '`':
2209
 
      if (str_char == '\0')     /* open string */
2210
 
        str_char = *ptr;
 
2198
      // open string
 
2199
      if (str_char == '\0')
 
2200
        str_char = *ptr;
2211
2201
      else if (str_char == *ptr)   /* close string */
2212
 
        str_char = '\0';
2213
 
      fixed_buffer.append(ptr,1);
 
2202
        str_char = '\0';
 
2203
      g_string_append_len(fixed_buffer, ptr, 1);
2214
2204
      break;
2215
2205
    case '\n':
2216
 
      /* 
 
2206
      /*
2217
2207
         not in string, change to space
2218
 
         if in string, leave it alone 
 
2208
         if in string, leave it alone
2219
2209
      */
2220
 
      fixed_buffer.append(str_char == '\0' ? " " : "\n");
 
2210
      g_string_append(fixed_buffer,(str_char == '\0') ? " " : "\n");
2221
2211
      total_lines++;
2222
2212
      break;
2223
2213
    case '\\':
2224
 
      fixed_buffer.append('\\');
 
2214
      g_string_append_c(fixed_buffer, '\\');
2225
2215
      /* need to see if the backslash is escaping anything */
2226
 
      if (str_char) 
 
2216
      if (str_char)
2227
2217
      {
2228
 
        ptr++;
2229
 
        /* special characters that need escaping */
2230
 
        if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
2231
 
          fixed_buffer.append(ptr,1);
2232
 
        else
2233
 
          ptr--;
 
2218
        ptr++;
 
2219
        /* special characters that need escaping */
 
2220
        if (*ptr == '\'' || *ptr == '"' || *ptr == '\\')
 
2221
          g_string_append_len(fixed_buffer, ptr, 1);
 
2222
        else
 
2223
          ptr--;
2234
2224
      }
2235
2225
      break;
2236
 
      
2237
2226
    default:
2238
 
      fixed_buffer.append(ptr,1);
 
2227
      g_string_append_len(fixed_buffer, ptr, 1);
2239
2228
    }
2240
2229
    ptr++;
2241
2230
  }
2242
 
  if (total_lines > 1)                  
2243
 
    add_history(fixed_buffer.ptr());
 
2231
  if (total_lines > 1)
 
2232
    add_history(fixed_buffer->str);
2244
2233
}
2245
2234
 
2246
 
/*      
 
2235
/*
2247
2236
  returns 0 if line matches the previous history entry
2248
2237
  returns 1 if the line doesn't match the previous history entry
2249
2238
*/
2250
 
static int not_in_history(const char *line) 
 
2239
static int not_in_history(const char *line)
2251
2240
{
2252
2241
  HIST_ENTRY *oldhist = history_get(history_length);
2253
 
  
 
2242
 
2254
2243
  if (oldhist == 0)
2255
2244
    return 1;
2256
2245
  if (strcmp(oldhist->line,line) == 0)
2512
2501
}
2513
2502
}
2514
2503
#endif
2515
 
#endif /* HAVE_READLINE */
2516
2504
 
2517
2505
 
2518
2506
static int reconnect(void)
2521
2509
  if (opt_reconnect)
2522
2510
  {
2523
2511
    put_info("No connection. Trying to reconnect...",INFO_INFO);
2524
 
    (void) com_connect((String *) 0, 0);
 
2512
    (void) com_connect((GString *) 0, 0);
2525
2513
    if (opt_rehash)
2526
2514
      com_rehash(NULL, NULL);
2527
2515
  }
2590
2578
}
2591
2579
 
2592
2580
 
2593
 
static int com_server_help(String *buffer __attribute__((unused)),
2594
 
                           char *line __attribute__((unused)), char *help_arg)
 
2581
static int com_server_help(GString *buffer,
 
2582
                           char *line __attribute__((unused)),
 
2583
                           char *help_arg)
2595
2584
{
2596
2585
  MYSQL_ROW cur;
2597
 
  const char *server_cmd= buffer->ptr();
 
2586
  const char *server_cmd= buffer->str;
2598
2587
  char cmd_buf[100];
2599
2588
  MYSQL_RES *result;
2600
2589
  int error;
2601
 
  
 
2590
 
2602
2591
  if (help_arg[0] != '\'')
2603
2592
  {
2604
 
        char *end_arg= strend(help_arg);
2605
 
        if(--end_arg)
2606
 
        {
2607
 
                while (my_isspace(charset_info,*end_arg))
2608
 
          end_arg--;
2609
 
                *++end_arg= '\0';
2610
 
        }
2611
 
        (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
 
2593
    char *end_arg= strend(help_arg);
 
2594
    if(--end_arg)
 
2595
    {
 
2596
      while (my_isspace(charset_info,*end_arg))
 
2597
        end_arg--;
 
2598
      *++end_arg= '\0';
 
2599
    }
 
2600
    (void) strxnmov(cmd_buf, sizeof(cmd_buf), "help '", help_arg, "'", NullS);
2612
2601
    server_cmd= cmd_buf;
2613
2602
  }
2614
 
  
 
2603
 
2615
2604
  if (!status.batch)
2616
2605
  {
2617
 
    old_buffer= *buffer;
2618
 
    old_buffer.copy();
 
2606
    old_buffer= g_string_new(buffer->str);
2619
2607
  }
2620
2608
 
2621
2609
  if (!connected && reconnect())
2687
2675
}
2688
2676
 
2689
2677
static int
2690
 
com_help(String *buffer __attribute__((unused)),
 
2678
com_help(GString *buffer __attribute__((unused)),
2691
2679
         char *line __attribute__((unused)))
2692
2680
{
2693
2681
  register int i, j;
2718
2706
}
2719
2707
 
2720
2708
 
2721
 
        /* ARGSUSED */
2722
2709
static int
2723
 
com_clear(String *buffer,char *line __attribute__((unused)))
 
2710
com_clear(GString *buffer,char *line __attribute__((unused)))
2724
2711
{
2725
 
#ifdef HAVE_READLINE
2726
2712
  if (status.add_to_history)
2727
2713
    fix_history(buffer);
2728
 
#endif
2729
 
  buffer->length(0);
 
2714
  g_string_truncate(buffer, 0);
2730
2715
  return 0;
2731
2716
}
2732
2717
 
2733
 
        /* ARGSUSED */
2734
2718
static int
2735
 
com_charset(String *buffer __attribute__((unused)), char *line)
 
2719
com_charset(GString *buffer __attribute__((unused)), char *line)
2736
2720
{
2737
2721
  char buff[256], *param;
2738
2722
  CHARSET_INFO * new_cs;
2762
2746
          -1 if not fatal error
2763
2747
          1  if fatal error
2764
2748
*/
2765
 
 
2766
 
 
2767
2749
static int
2768
 
com_go(String *buffer,char *line __attribute__((unused)))
 
2750
com_go(GString *buffer,
 
2751
       char *line __attribute__((unused)))
2769
2752
{
2770
 
  char          buff[200]; /* about 110 chars used so far */
2771
 
  char          time_buff[52+3+1]; /* time max + space&parens + NUL */
2772
 
  MYSQL_RES     *result;
2773
 
  ulong         timer, warnings= 0;
2774
 
  uint          error= 0;
 
2753
  char          buff[200]; /* about 110 chars used so far */
 
2754
  char          time_buff[52+3+1]; /* time max + space&parens + NUL */
 
2755
  MYSQL_RES     *result;
 
2756
  ulong         timer, warnings= 0;
 
2757
  uint          error= 0;
2775
2758
  int           err= 0;
2776
2759
 
2777
2760
  interrupted_query= 0;
2778
2761
  if (!status.batch)
2779
2762
  {
2780
 
    old_buffer= *buffer;                        // Save for edit command
2781
 
    old_buffer.copy();
 
2763
    // Save for edit command
 
2764
    old_buffer= g_string_new(buffer->str);
2782
2765
  }
2783
2766
 
2784
2767
  /* Remove garbage for nicer messages */
2785
 
  remove_cntrl(*buffer);
 
2768
  remove_cntrl(buffer);
2786
2769
 
2787
 
  if (buffer->is_empty())
 
2770
  if (buffer->len == 0)
2788
2771
  {
2789
 
    if (status.batch)                           // Ignore empty quries
 
2772
    // Ignore empty quries
 
2773
    if (status.batch)
2790
2774
      return 0;
2791
2775
    return put_info("No query specified\n",INFO_ERROR);
2792
2776
 
2793
2777
  }
2794
2778
  if (!connected && reconnect())
2795
2779
  {
2796
 
    buffer->length(0);                          // Remove query on error
 
2780
    // Remove query on error
 
2781
    g_string_truncate(buffer, 0);
2797
2782
    return opt_reconnect ? -1 : 1;          // Fatal error
2798
2783
  }
2799
2784
  if (verbose)
2800
 
    (void) com_print(buffer,0);
 
2785
    (void) com_print(buffer, 0);
2801
2786
 
2802
2787
  if (skip_updates &&
2803
 
      (buffer->length() < 4 || my_strnncoll(charset_info,
2804
 
                                            (const uchar*)buffer->ptr(),4,
2805
 
                                            (const uchar*)"SET ",4)))
 
2788
      (buffer->len < 4)
 
2789
      || g_string_equal(g_string_new_len(buffer->str,4),
 
2790
                        g_string_new("SET ")))
2806
2791
  {
2807
2792
    (void) put_info("Ignoring query to other database",INFO_INFO);
2808
2793
    return 0;
2810
2795
 
2811
2796
  timer=start_timer();
2812
2797
  executing_query= 1;
2813
 
  error= mysql_real_query_for_lazy(buffer->ptr(),buffer->length());
 
2798
  error= mysql_real_query_for_lazy(buffer->str,buffer->len);
2814
2799
 
2815
 
#ifdef HAVE_READLINE
2816
 
  if (status.add_to_history) 
2817
 
  {  
2818
 
    buffer->append(vertical ? "\\G" : delimiter);
 
2800
  if (status.add_to_history)
 
2801
  {
 
2802
    g_string_append(buffer, vertical ? "\\G" : delimiter);
2819
2803
    /* Append final command onto history */
2820
2804
    fix_history(buffer);
2821
2805
  }
2822
 
#endif
2823
2806
 
2824
 
  buffer->length(0);
 
2807
  g_string_truncate(buffer, 0);
2825
2808
 
2826
2809
  if (error)
2827
2810
    goto end;
2989
2972
 
2990
2973
 
2991
2974
static int
2992
 
com_ego(String *buffer,char *line)
 
2975
com_ego(GString *buffer,char *line)
2993
2976
{
2994
2977
  int result;
2995
2978
  bool oldvertical=vertical;
3089
3072
static void
3090
3073
print_table_data(MYSQL_RES *result)
3091
3074
{
3092
 
  String separator(256);
3093
 
  MYSQL_ROW     cur;
3094
 
  MYSQL_FIELD   *field;
3095
 
  bool          *num_flag;
 
3075
  GString       *separator;
 
3076
  MYSQL_ROW     cur;
 
3077
  MYSQL_FIELD   *field;
 
3078
  bool          *num_flag;
3096
3079
 
3097
 
  num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result));
 
3080
  num_flag=(bool*) my_malloc(sizeof(bool)*mysql_num_fields(result),
 
3081
                             MYF(MY_WME));
3098
3082
  if (column_types_flag)
3099
3083
  {
3100
3084
    print_field_types(result);
3102
3086
      return;
3103
3087
    mysql_field_seek(result,0);
3104
3088
  }
3105
 
  separator.copy("+",1,charset_info);
 
3089
  separator = g_string_new("+");
3106
3090
  while ((field = mysql_fetch_field(result)))
3107
3091
  {
3108
3092
    uint length= column_names ? field->name_length : 0;
3185
3169
        if (num_flag[off] != 0) /* if it is numeric, we right-justify it */
3186
3170
          tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, TRUE);
3187
3171
        else 
3188
 
          tee_print_sized_data(buffer, data_length, field_max_length+extra_padding, FALSE);
 
3172
          tee_print_sized_data(buffer, data_length,
 
3173
                               field_max_length+extra_padding, FALSE);
3189
3174
      }
3190
3175
      tee_fputs(" | ", PAGER);
3191
3176
    }
3192
3177
    (void) tee_fputs("\n", PAGER);
3193
3178
  }
3194
3179
  tee_puts((char*) separator.ptr(), PAGER);
3195
 
  my_afree((uchar*) num_flag);
 
3180
  my_free(num_flag, MYF(MY_ALLOW_ZERO_PTR));
3196
3181
}
3197
3182
 
3198
3183
/**
3199
3184
  Return the length of a field after it would be rendered into text.
3200
3185
 
3201
3186
  This doesn't know or care about multibyte characters.  Assume we're
3202
 
  using such a charset.  We can't know that all of the upcoming rows 
 
3187
  using such a charset.  We can't know that all of the upcoming rows
3203
3188
  for this column will have bytes that each render into some fraction
3204
3189
  of a character.  It's at least possible that a row has bytes that 
3205
3190
  all render into one character each, and so the maximum length is 
3535
3520
}
3536
3521
 
3537
3522
static int
3538
 
com_tee(String *buffer __attribute__((__unused__)), char *line )
 
3523
com_tee(GString *buffer __attribute__((__unused__)), char *line )
3539
3524
{
3540
3525
  char file_name[FN_REFLEN], *end, *param;
3541
3526
 
3579
3564
 
3580
3565
 
3581
3566
static int
3582
 
com_notee(String *buffer __attribute__((unused)),
 
3567
com_notee(GString *buffer __attribute__((unused)),
3583
3568
          char *line __attribute__((unused)))
3584
3569
{
3585
3570
  if (opt_outfile)
3594
3579
 
3595
3580
#ifdef USE_POPEN
3596
3581
static int
3597
 
com_pager(String *buffer, char *line __attribute__((unused)))
 
3582
com_pager(GString *buffer, char *line __attribute__((unused)))
3598
3583
{
3599
3584
  char pager_name[FN_REFLEN], *end, *param;
3600
3585
 
3637
3622
 
3638
3623
 
3639
3624
static int
3640
 
com_nopager(String *buffer __attribute__((unused)),
 
3625
com_nopager(GString *buffer __attribute__((unused)),
3641
3626
            char *line __attribute__((unused)))
3642
3627
{
3643
3628
  strmov(pager, "stdout");
3655
3640
 
3656
3641
#ifdef USE_POPEN
3657
3642
static int
3658
 
com_edit(String *buffer,char *line __attribute__((unused)))
 
3643
com_edit(GString *buffer,char *line __attribute__((unused)))
3659
3644
{
3660
3645
  char  filename[FN_REFLEN],buff[160];
3661
3646
  int   fd,tmp;
3698
3683
/* If arg is given, exit without errors. This happens on command 'quit' */
3699
3684
 
3700
3685
static int
3701
 
com_quit(String *buffer __attribute__((unused)),
 
3686
com_quit(GString *buffer __attribute__((unused)),
3702
3687
         char *line __attribute__((unused)))
3703
3688
{
3704
3689
  /* let the screen auto close on a normal shutdown */
3707
3692
}
3708
3693
 
3709
3694
static int
3710
 
com_rehash(String *buffer __attribute__((unused)),
 
3695
com_rehash(GString *buffer __attribute__((unused)),
3711
3696
         char *line __attribute__((unused)))
3712
3697
{
3713
 
#ifdef HAVE_READLINE
3714
3698
  build_completion_hash(1, 0);
3715
 
#endif
3716
3699
  return 0;
3717
3700
}
3718
3701
 
3719
3702
 
3720
3703
#ifdef USE_POPEN
3721
3704
static int
3722
 
com_shell(String *buffer, char *line __attribute__((unused)))
 
3705
com_shell(GString *buffer, char *line __attribute__((unused)))
3723
3706
{
3724
3707
  char *shell_cmd;
3725
3708
 
3746
3729
 
3747
3730
 
3748
3731
static int
3749
 
com_print(String *buffer,char *line __attribute__((unused)))
 
3732
com_print(GString *buffer,char *line __attribute__((unused)))
3750
3733
{
3751
3734
  tee_puts("--------------", stdout);
3752
3735
  (void) tee_fputs(buffer->c_ptr(), stdout);
3758
3741
 
3759
3742
        /* ARGSUSED */
3760
3743
static int
3761
 
com_connect(String *buffer, char *line)
 
3744
com_connect(GString *buffer, char *line)
3762
3745
{
3763
3746
  char *tmp, buff[256];
3764
3747
  bool save_rehash= opt_rehash;
3811
3794
}
3812
3795
 
3813
3796
 
3814
 
static int com_source(String *buffer __attribute__((__unused__)), char *line)
 
3797
static int com_source(GString *buffer __attribute__((__unused__)), char *line)
3815
3798
{
3816
3799
  char source_name[FN_REFLEN], *end, *param;
3817
3800
  LINE_BUFFER *line_buff;
3865
3848
 
3866
3849
        /* ARGSUSED */
3867
3850
static int
3868
 
com_delimiter(String *buffer __attribute__((unused)), char *line)
 
3851
com_delimiter(GString *buffer __attribute__((unused)), char *line)
3869
3852
{
3870
3853
  char buff[256], *tmp;
3871
3854
 
3894
3877
 
3895
3878
        /* ARGSUSED */
3896
3879
static int
3897
 
com_use(String *buffer __attribute__((unused)), char *line)
 
3880
com_use(GString *buffer __attribute__((unused)), char *line)
3898
3881
{
3899
3882
  char *tmp, buff[FN_REFLEN + 1];
3900
3883
  int select_db;
3957
3940
    }
3958
3941
    my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
3959
3942
    current_db=my_strdup(tmp,MYF(MY_WME));
3960
 
#ifdef HAVE_READLINE
3961
3943
    if (select_db > 1)
3962
3944
      build_completion_hash(opt_rehash, 1);
3963
 
#endif
3964
3945
  }
3965
3946
 
3966
3947
  put_info("Database changed",INFO_INFO);
3968
3949
}
3969
3950
 
3970
3951
static int
3971
 
com_warnings(String *buffer __attribute__((unused)),
 
3952
com_warnings(GString *buffer __attribute__((unused)),
3972
3953
   char *line __attribute__((unused)))
3973
3954
{
3974
3955
  show_warnings = 1;
3977
3958
}
3978
3959
 
3979
3960
static int
3980
 
com_nowarnings(String *buffer __attribute__((unused)),
 
3961
com_nowarnings(GString *buffer __attribute__((unused)),
3981
3962
   char *line __attribute__((unused)))
3982
3963
{
3983
3964
  show_warnings = 0;
4100
4081
    return -1;                                  // Retryable
4101
4082
  }
4102
4083
  connected=1;
4103
 
#ifndef EMBEDDED_LIBRARY
4104
4084
  mysql.reconnect= debug_info_flag; // We want to know if this happens
4105
 
#else
4106
 
  mysql.reconnect= 1;
4107
 
#endif
4108
 
#ifdef HAVE_READLINE
4109
4085
  build_completion_hash(opt_rehash, 1);
4110
 
#endif
4111
4086
  return 0;
4112
4087
}
4113
4088
 
4148
4123
 
4149
4124
 
4150
4125
static int
4151
 
com_status(String *buffer __attribute__((unused)),
 
4126
com_status(GString *buffer __attribute__((unused)),
4152
4127
           char *line __attribute__((unused)))
4153
4128
{
4154
4129
  const char *status_str;
4376
4351
}  
4377
4352
 
4378
4353
 
4379
 
static void remove_cntrl(String &buffer)
 
4354
static void remove_cntrl(GString *buffer)
4380
4355
{
4381
4356
  char *start,*end;
4382
4357
  end=(start=(char*) buffer.ptr())+buffer.length();
4537
4512
      }
4538
4513
      case 'p':
4539
4514
      {
4540
 
#ifndef EMBEDDED_LIBRARY
4541
4515
        if (!connected)
4542
4516
        {
4543
4517
          processed_prompt.append("not_connected");
4557
4531
          char *pos=strrchr(mysql.unix_socket,'/');
4558
4532
          processed_prompt.append(pos ? pos+1 : mysql.unix_socket);
4559
4533
        }
4560
 
#endif
4561
4534
      }
4562
4535
        break;
4563
4536
      case 'U':
4681
4654
  }
4682
4655
}
4683
4656
 
4684
 
static int com_prompt(String *buffer __attribute__((__unused__)), char *line)
 
4657
static int com_prompt(GString *buffer __attribute__((__unused__)), char *line)
4685
4658
{
4686
4659
  char *ptr=strchr(line, ' ');
4687
4660
  prompt_counter = 0;