1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

* Includes tab completion. It's not magic, but it's very cool. At any

rate
  it's better than what used to be there.

* Does proper SQL "host variable" substitution as pointed out by Andreas
  Zeugwetter (thanks): select * from :foo; Also some changes in how ':'
  and ';' are treated (escape with \ to send to backend). This does
_not_
  affect the '::' cast operator, but perhaps others that contain : or ;
  (but there are none right now).

* To show description with a <something> listing, append '?' to command
  name, e.g., \df?. This seemed to be the convenient and logical
solution.
  Or append a '+' to see more useless information, e.g., \df+.

* Fixed fflush()'ing bug pointed out by Jan during the regression test
  discussion.

* Added LastOid variable. This ought to take care of TODO item "Add a
  function to return the last inserted oid, for use in psql scripts"
  (under CLIENTS)
  E.g.,
insert into foo values(...);
insert into bar values(..., :LastOid);
\echo $LastOid

* \d command shows constraints, rules, and triggers defined on the table
  (in addition to indices)

* Various fixes, optimizations, corrections

* Documentation update as well


Note: This now requires snprintf(), which, if necessary, is taken from
src/backend/port. This is certainly a little weird, but it should
suffice
until a source tree cleanup is done.

Enjoy.

--
Peter Eisentraut                  Sernanders väg 10:115
This commit is contained in:
Bruce Momjian
1999-11-26 04:24:17 +00:00
parent c83b4d1cd8
commit 78bc83fedf
22 changed files with 1763 additions and 788 deletions

View File

@ -33,7 +33,7 @@
#endif
/* functions for use in this file only */
/* functions for use in this file */
static backslashResult exec_command(const char *cmd,
char *const * options,
@ -41,16 +41,24 @@ static backslashResult exec_command(const char *cmd,
PQExpBuffer query_buf,
PsqlSettings *pset);
static bool
do_edit(const char *filename_arg, PQExpBuffer query_buf);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
static char *
unescape(const char *source, PsqlSettings *pset);
static char * unescape(const char *source, PsqlSettings *pset);
static bool
do_shell(const char *command);
static bool do_connect(const char *new_dbname,
const char *new_user,
PsqlSettings *pset);
static bool do_shell(const char *command);
/*
* Perhaps this should be changed to "infinity",
* but there is no convincing reason to bother
* at this point.
*/
#define NR_OPTIONS 16
/*----------
* HandleSlashCmds:
@ -78,7 +86,7 @@ HandleSlashCmds(PsqlSettings *pset,
{
backslashResult status = CMD_SKIP_LINE;
char *my_line;
char *options[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char *options[NR_OPTIONS+1];
char *token;
const char *options_string = NULL;
const char *cmd;
@ -120,7 +128,7 @@ HandleSlashCmds(PsqlSettings *pset,
i = 0;
token = strtokx(options_string, " \t", "\"'`", '\\', &quote, &pos);
for (i = 0; token && i < 16; i++)
for (i = 0; token && i < NR_OPTIONS; i++)
{
switch (quote)
{
@ -194,14 +202,15 @@ HandleSlashCmds(PsqlSettings *pset,
options[i] = xstrdup(interpolate_var(token + 1, pset));
else
options[i] = xstrdup(token);
break;
}
if (continue_parse)
break;
token = strtokx(NULL, " \t", "\"'`", '\\', &quote, &pos);
}
} /* for */
options[i] = NULL;
}
cmd = my_line;
@ -216,11 +225,11 @@ HandleSlashCmds(PsqlSettings *pset,
* arguments to start immediately after the command, but that is
* no longer encouraged.
*/
const char *new_options[17];
const char *new_options[NR_OPTIONS+1];
char new_cmd[2];
int i;
for (i = 1; i < 17; i++)
for (i = 1; i < NR_OPTIONS+1; i++)
new_options[i] = options[i - 1];
new_options[0] = cmd + 1;
@ -249,7 +258,7 @@ HandleSlashCmds(PsqlSettings *pset,
}
/* clean up */
for (i = 0; i < 16 && options[i]; i++)
for (i = 0; i < NR_OPTIONS && options[i]; i++)
free(options[i]);
free(my_line);
@ -274,10 +283,7 @@ exec_command(const char *cmd,
backslashResult status = CMD_SKIP_LINE;
/*
* \a -- toggle field alignment This is deprecated and makes no sense,
* but we keep it around.
*/
/* \a -- toggle field alignment This makes little sense but we keep it around. */
if (strcmp(cmd, "a") == 0)
{
if (pset->popt.topt.format != PRINT_ALIGNED)
@ -287,22 +293,19 @@ exec_command(const char *cmd,
}
/*
* \C -- override table title (formerly change HTML caption) This is
* deprecated.
*/
/* \C -- override table title (formerly change HTML caption) */
else if (strcmp(cmd, "C") == 0)
success = do_pset("title", options[0], &pset->popt, quiet);
/*
/*----------
* \c or \connect -- connect to new database or as different user
*
* \c foo bar : connect to db "foo" as user "bar" \c foo [-] :
* connect to db "foo" as current user \c - bar : connect to
* current db as user "bar" \c : connect to default db as
* default user
* \c foo bar: connect to db "foo" as user "bar"
* \c foo [-]: connect to db "foo" as current user
* \c - bar: connect to current db as user "bar"
* \c: connect to default db as default user
*----------
*/
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
{
@ -335,35 +338,39 @@ exec_command(const char *cmd,
/* \d* commands */
else if (cmd[0] == 'd')
{
bool show_verbose = strchr(cmd, '+') ? true : false;
bool show_desc = strchr(cmd, '?') ? true : false;
switch (cmd[1])
{
case '\0':
case '?':
if (options[0])
success = describeTableDetails(options[0], pset);
success = describeTableDetails(options[0], pset, show_desc);
else
success = listTables("tvs", NULL, pset); /* standard listing of
* interesting things */
/* standard listing of interesting things */
success = listTables("tvs", NULL, pset, show_desc);
break;
case 'a':
success = describeAggregates(options[0], pset);
success = describeAggregates(options[0], pset, show_verbose, show_desc);
break;
case 'd':
success = objectDescription(options[0], pset);
break;
case 'f':
success = describeFunctions(options[0], pset);
success = describeFunctions(options[0], pset, show_verbose, show_desc);
break;
case 'l':
success = do_lo_list(pset);
success = do_lo_list(pset, show_desc);
break;
case 'o':
success = describeOperators(options[0], pset);
success = describeOperators(options[0], pset, show_verbose, show_desc);
break;
case 'p':
success = permissionsList(options[0], pset);
break;
case 'T':
success = describeTypes(options[0], pset);
success = describeTypes(options[0], pset, show_verbose, show_desc);
break;
case 't':
case 'v':
@ -371,9 +378,9 @@ exec_command(const char *cmd,
case 's':
case 'S':
if (cmd[1] == 'S' && cmd[2] == '\0')
success = listTables("Stvs", NULL, pset);
success = listTables("Stvs", NULL, pset, show_desc);
else
success = listTables(&cmd[1], options[0], pset);
success = listTables(&cmd[1], options[0], pset, show_desc);
break;
default:
status = CMD_UNKNOWN;
@ -399,14 +406,10 @@ exec_command(const char *cmd,
fputs("\n", stdout);
}
/*
* \f -- change field separator (This is deprecated in favour of
* \pset.)
*/
/* \f -- change field separator */
else if (strcmp(cmd, "f") == 0)
success = do_pset("fieldsep", options[0], &pset->popt, quiet);
/* \g means send query */
else if (strcmp(cmd, "g") == 0)
{
@ -419,12 +422,27 @@ exec_command(const char *cmd,
/* help */
else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
helpSQL(options_string);
{
char buf[256] = "";
int i;
for (i=0; options && options[i] && strlen(buf)<255; i++)
{
strncat(buf, options[i], 255 - strlen(buf));
if (strlen(buf)<255 && options[i+1])
strcat(buf, " ");
}
buf[255] = '\0';
helpSQL(buf);
}
/* HTML mode */
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
success = do_pset("format", "html", &pset->popt, quiet);
{
if (pset->popt.topt.format != PRINT_HTML)
success = do_pset("format", "html", &pset->popt, quiet);
else
success = do_pset("format", "aligned", &pset->popt, quiet);
}
/* \i is include file */
@ -439,9 +457,12 @@ exec_command(const char *cmd,
success = process_file(options[0], pset);
}
/* \l is list databases */
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
success = listAllDbs(pset);
success = listAllDbs(pset, false);
else if (strcmp(cmd, "l?") == 0 || strcmp(cmd, "list?") == 0)
success = listAllDbs(pset, true);
/* large object things */
@ -470,7 +491,9 @@ exec_command(const char *cmd,
}
else if (strcmp(cmd + 3, "list") == 0)
success = do_lo_list(pset);
success = do_lo_list(pset, false);
else if (strcmp(cmd + 3, "list?") == 0)
success = do_lo_list(pset, true);
else if (strcmp(cmd + 3, "unlink") == 0)
{
@ -828,7 +851,7 @@ unescape(const char *source, PsqlSettings *pset)
* Returns true if all ok, false if the new connection couldn't be established
* but the old one was set back. Otherwise it terminates the program.
*/
bool
static bool
do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
{
PGconn *oldconn = pset->db;