Skip to content

Commit 78bc83f

Browse files
committed
* 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
1 parent c83b4d1 commit 78bc83f

22 files changed

+1769
-794
lines changed

doc/src/sgml/ref/psql-ref.sgml

Lines changed: 163 additions & 169 deletions
Large diffs are not rendered by default.

src/bin/psql/Makefile.in

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
#
99
# IDENTIFICATION
10-
# $Header: /cvsroot/pgsql/src/bin/psql/Attic/Makefile.in,v 1.17 1999/11/08 15:59:59 momjian Exp $
10+
# $Header: /cvsroot/pgsql/src/bin/psql/Attic/Makefile.in,v 1.18 1999/11/26 04:24:16 momjian Exp $
1111
#
1212
#-------------------------------------------------------------------------
1313

@@ -30,10 +30,18 @@ endif
3030

3131
OBJS=command.o common.o help.o input.o stringutils.o mainloop.o \
3232
copy.o startup.o prompt.o variables.o large_obj.o print.o describe.o \
33-
@STRDUP@ @STRERROR2@
33+
tab-complete.o @STRDUP@ @STRERROR2@ @SNPRINTF@
3434

3535
all: submake psql
3636

37+
# Move this to the utils directory
38+
ifneq (@SNPRINTF@,)
39+
OBJS+=../../backend/port/snprintf.o
40+
41+
../../backend/port/snprintf.o:
42+
$(MAKE) -C ../../backend/port snprintf.o
43+
endif
44+
3745
psql: $(OBJS) $(LIBPQDIR)/libpq.a
3846
$(CC) -o psql -L$(LIBPQDIR) $(OBJS) -lpq $(LDFLAGS)
3947

@@ -69,7 +77,7 @@ clean:
6977
# sql_help.h is gone, for it needs the docs in the right place to be
7078
# regenerated. -- (pe)
7179

72-
distclean: clean
80+
maintainer-clean: clean
7381
rm -f sql_help.h
7482

7583
ifeq (depend,$(wildcard depend))

src/bin/psql/command.c

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,31 @@
3333
#endif
3434

3535

36-
/* functions for use in this file only */
36+
/* functions for use in this file */
3737

3838
static backslashResult exec_command(const char *cmd,
3939
char *const * options,
4040
const char *options_string,
4141
PQExpBuffer query_buf,
4242
PsqlSettings *pset);
4343

44-
static bool
45-
do_edit(const char *filename_arg, PQExpBuffer query_buf);
44+
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
4645

47-
static char *
48-
unescape(const char *source, PsqlSettings *pset);
46+
static char * unescape(const char *source, PsqlSettings *pset);
47+
48+
static bool do_connect(const char *new_dbname,
49+
const char *new_user,
50+
PsqlSettings *pset);
4951

50-
static bool
51-
do_shell(const char *command);
5252

53+
static bool do_shell(const char *command);
54+
55+
/*
56+
* Perhaps this should be changed to "infinity",
57+
* but there is no convincing reason to bother
58+
* at this point.
59+
*/
60+
#define NR_OPTIONS 16
5361

5462

5563
/*----------
@@ -78,7 +86,7 @@ HandleSlashCmds(PsqlSettings *pset,
7886
{
7987
backslashResult status = CMD_SKIP_LINE;
8088
char *my_line;
81-
char *options[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
89+
char *options[NR_OPTIONS+1];
8290
char *token;
8391
const char *options_string = NULL;
8492
const char *cmd;
@@ -120,7 +128,7 @@ HandleSlashCmds(PsqlSettings *pset,
120128
i = 0;
121129
token = strtokx(options_string, " \t", "\"'`", '\\', &quote, &pos);
122130

123-
for (i = 0; token && i < 16; i++)
131+
for (i = 0; token && i < NR_OPTIONS; i++)
124132
{
125133
switch (quote)
126134
{
@@ -194,14 +202,15 @@ HandleSlashCmds(PsqlSettings *pset,
194202
options[i] = xstrdup(interpolate_var(token + 1, pset));
195203
else
196204
options[i] = xstrdup(token);
197-
break;
198205
}
199206

200207
if (continue_parse)
201208
break;
202209

203210
token = strtokx(NULL, " \t", "\"'`", '\\', &quote, &pos);
204-
}
211+
} /* for */
212+
213+
options[i] = NULL;
205214
}
206215

207216
cmd = my_line;
@@ -216,11 +225,11 @@ HandleSlashCmds(PsqlSettings *pset,
216225
* arguments to start immediately after the command, but that is
217226
* no longer encouraged.
218227
*/
219-
const char *new_options[17];
228+
const char *new_options[NR_OPTIONS+1];
220229
char new_cmd[2];
221230
int i;
222231

223-
for (i = 1; i < 17; i++)
232+
for (i = 1; i < NR_OPTIONS+1; i++)
224233
new_options[i] = options[i - 1];
225234
new_options[0] = cmd + 1;
226235

@@ -249,7 +258,7 @@ HandleSlashCmds(PsqlSettings *pset,
249258
}
250259

251260
/* clean up */
252-
for (i = 0; i < 16 && options[i]; i++)
261+
for (i = 0; i < NR_OPTIONS && options[i]; i++)
253262
free(options[i]);
254263

255264
free(my_line);
@@ -274,10 +283,7 @@ exec_command(const char *cmd,
274283
backslashResult status = CMD_SKIP_LINE;
275284

276285

277-
/*
278-
* \a -- toggle field alignment This is deprecated and makes no sense,
279-
* but we keep it around.
280-
*/
286+
/* \a -- toggle field alignment This makes little sense but we keep it around. */
281287
if (strcmp(cmd, "a") == 0)
282288
{
283289
if (pset->popt.topt.format != PRINT_ALIGNED)
@@ -287,22 +293,19 @@ exec_command(const char *cmd,
287293
}
288294

289295

290-
/*
291-
* \C -- override table title (formerly change HTML caption) This is
292-
* deprecated.
293-
*/
296+
/* \C -- override table title (formerly change HTML caption) */
294297
else if (strcmp(cmd, "C") == 0)
295298
success = do_pset("title", options[0], &pset->popt, quiet);
296299

297300

298-
299-
/*
301+
/*----------
300302
* \c or \connect -- connect to new database or as different user
301303
*
302-
* \c foo bar : connect to db "foo" as user "bar" \c foo [-] :
303-
* connect to db "foo" as current user \c - bar : connect to
304-
* current db as user "bar" \c : connect to default db as
305-
* default user
304+
* \c foo bar: connect to db "foo" as user "bar"
305+
* \c foo [-]: connect to db "foo" as current user
306+
* \c - bar: connect to current db as user "bar"
307+
* \c: connect to default db as default user
308+
*----------
306309
*/
307310
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
308311
{
@@ -335,45 +338,49 @@ exec_command(const char *cmd,
335338
/* \d* commands */
336339
else if (cmd[0] == 'd')
337340
{
341+
bool show_verbose = strchr(cmd, '+') ? true : false;
342+
bool show_desc = strchr(cmd, '?') ? true : false;
343+
338344
switch (cmd[1])
339345
{
340346
case '\0':
347+
case '?':
341348
if (options[0])
342-
success = describeTableDetails(options[0], pset);
349+
success = describeTableDetails(options[0], pset, show_desc);
343350
else
344-
success = listTables("tvs", NULL, pset); /* standard listing of
345-
* interesting things */
351+
/* standard listing of interesting things */
352+
success = listTables("tvs", NULL, pset, show_desc);
346353
break;
347354
case 'a':
348-
success = describeAggregates(options[0], pset);
355+
success = describeAggregates(options[0], pset, show_verbose, show_desc);
349356
break;
350357
case 'd':
351358
success = objectDescription(options[0], pset);
352359
break;
353360
case 'f':
354-
success = describeFunctions(options[0], pset);
361+
success = describeFunctions(options[0], pset, show_verbose, show_desc);
355362
break;
356363
case 'l':
357-
success = do_lo_list(pset);
364+
success = do_lo_list(pset, show_desc);
358365
break;
359366
case 'o':
360-
success = describeOperators(options[0], pset);
367+
success = describeOperators(options[0], pset, show_verbose, show_desc);
361368
break;
362369
case 'p':
363370
success = permissionsList(options[0], pset);
364371
break;
365372
case 'T':
366-
success = describeTypes(options[0], pset);
373+
success = describeTypes(options[0], pset, show_verbose, show_desc);
367374
break;
368375
case 't':
369376
case 'v':
370377
case 'i':
371378
case 's':
372379
case 'S':
373380
if (cmd[1] == 'S' && cmd[2] == '\0')
374-
success = listTables("Stvs", NULL, pset);
381+
success = listTables("Stvs", NULL, pset, show_desc);
375382
else
376-
success = listTables(&cmd[1], options[0], pset);
383+
success = listTables(&cmd[1], options[0], pset, show_desc);
377384
break;
378385
default:
379386
status = CMD_UNKNOWN;
@@ -399,14 +406,10 @@ exec_command(const char *cmd,
399406
fputs("\n", stdout);
400407
}
401408

402-
/*
403-
* \f -- change field separator (This is deprecated in favour of
404-
* \pset.)
405-
*/
409+
/* \f -- change field separator */
406410
else if (strcmp(cmd, "f") == 0)
407411
success = do_pset("fieldsep", options[0], &pset->popt, quiet);
408412

409-
410413
/* \g means send query */
411414
else if (strcmp(cmd, "g") == 0)
412415
{
@@ -419,12 +422,27 @@ exec_command(const char *cmd,
419422

420423
/* help */
421424
else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
422-
helpSQL(options_string);
423-
425+
{
426+
char buf[256] = "";
427+
int i;
428+
for (i=0; options && options[i] && strlen(buf)<255; i++)
429+
{
430+
strncat(buf, options[i], 255 - strlen(buf));
431+
if (strlen(buf)<255 && options[i+1])
432+
strcat(buf, " ");
433+
}
434+
buf[255] = '\0';
435+
helpSQL(buf);
436+
}
424437

425438
/* HTML mode */
426439
else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
427-
success = do_pset("format", "html", &pset->popt, quiet);
440+
{
441+
if (pset->popt.topt.format != PRINT_HTML)
442+
success = do_pset("format", "html", &pset->popt, quiet);
443+
else
444+
success = do_pset("format", "aligned", &pset->popt, quiet);
445+
}
428446

429447

430448
/* \i is include file */
@@ -439,9 +457,12 @@ exec_command(const char *cmd,
439457
success = process_file(options[0], pset);
440458
}
441459

460+
442461
/* \l is list databases */
443462
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
444-
success = listAllDbs(pset);
463+
success = listAllDbs(pset, false);
464+
else if (strcmp(cmd, "l?") == 0 || strcmp(cmd, "list?") == 0)
465+
success = listAllDbs(pset, true);
445466

446467

447468
/* large object things */
@@ -470,7 +491,9 @@ exec_command(const char *cmd,
470491
}
471492

472493
else if (strcmp(cmd + 3, "list") == 0)
473-
success = do_lo_list(pset);
494+
success = do_lo_list(pset, false);
495+
else if (strcmp(cmd + 3, "list?") == 0)
496+
success = do_lo_list(pset, true);
474497

475498
else if (strcmp(cmd + 3, "unlink") == 0)
476499
{
@@ -828,7 +851,7 @@ unescape(const char *source, PsqlSettings *pset)
828851
* Returns true if all ok, false if the new connection couldn't be established
829852
* but the old one was set back. Otherwise it terminates the program.
830853
*/
831-
bool
854+
static bool
832855
do_connect(const char *new_dbname, const char *new_user, PsqlSettings *pset)
833856
{
834857
PGconn *oldconn = pset->db;

src/bin/psql/command.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ backslashResult HandleSlashCmds(PsqlSettings *pset,
2929
PQExpBuffer query_buf,
3030
const char **end_of_cmd);
3131

32-
bool do_connect(const char *new_dbname,
33-
const char *new_user,
34-
PsqlSettings *pset);
35-
3632
bool process_file(const char *filename,
3733
PsqlSettings *pset);
3834

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy