Skip to content

Commit 00f4c29

Browse files
committed
psql: Add option to use expanded mode to all list commands.
This allows "x" to be appended to any psql list-like meta-command, forcing its output to be displayed in expanded mode. This improves readability in cases where the output is very wide. For example, "\dfx+" (or equivalently "\df+x") will produce a list of functions, with additional details, in expanded mode. This works with all \d* meta-commands, plus \l, \z, and \lo_list, with the one exception that the expanded mode option "x" cannot be appended to "\d" by itself, since "\dx" already means something else. Dean Rasheed, reviewed by Greg Sabino Mullane. Discussion: https://postgr.es/m/CAEZATCVXJk3KsmCncf7PAVbxdDAUDm3QzDgGT7mBYySWikuOYw@mail.gmail.com
1 parent 94b914f commit 00f4c29

File tree

6 files changed

+418
-131
lines changed

6 files changed

+418
-131
lines changed

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

+206-69
Large diffs are not rendered by default.

src/bin/psql/command.c

+61-7
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,10 @@ exec_command(const char *cmd,
377377
else if (strcmp(cmd, "if") == 0)
378378
status = exec_command_if(scan_state, cstack, query_buf);
379379
else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
380-
strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
380+
strcmp(cmd, "lx") == 0 || strcmp(cmd, "listx") == 0 ||
381+
strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0 ||
382+
strcmp(cmd, "lx+") == 0 || strcmp(cmd, "listx+") == 0 ||
383+
strcmp(cmd, "l+x") == 0 || strcmp(cmd, "list+x") == 0)
381384
status = exec_command_list(scan_state, active_branch, cmd);
382385
else if (strncmp(cmd, "lo_", 3) == 0)
383386
status = exec_command_lo(scan_state, active_branch, cmd);
@@ -424,7 +427,9 @@ exec_command(const char *cmd,
424427
query_buf, previous_buf);
425428
else if (strcmp(cmd, "x") == 0)
426429
status = exec_command_x(scan_state, active_branch);
427-
else if (strcmp(cmd, "z") == 0 || strcmp(cmd, "zS") == 0)
430+
else if (strcmp(cmd, "z") == 0 ||
431+
strcmp(cmd, "zS") == 0 || strcmp(cmd, "zx") == 0 ||
432+
strcmp(cmd, "zSx") == 0 || strcmp(cmd, "zxS") == 0)
428433
status = exec_command_z(scan_state, active_branch, cmd);
429434
else if (strcmp(cmd, "!") == 0)
430435
status = exec_command_shell_escape(scan_state, active_branch);
@@ -850,6 +855,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
850855
char *pattern;
851856
bool show_verbose,
852857
show_system;
858+
unsigned short int save_expanded;
853859

854860
/* We don't do SQLID reduction on the pattern yet */
855861
pattern = psql_scan_slash_option(scan_state,
@@ -858,6 +864,16 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
858864
show_verbose = strchr(cmd, '+') ? true : false;
859865
show_system = strchr(cmd, 'S') ? true : false;
860866

867+
/*
868+
* The 'x' option turns expanded mode on for this command only. This
869+
* is allowed in all \d* commands, except \d by itself, since \dx is a
870+
* separate command. So the 'x' option cannot appear immediately after
871+
* \d, but it can appear after \d followed by other options.
872+
*/
873+
save_expanded = pset.popt.topt.expanded;
874+
if (cmd[1] != '\0' && strchr(&cmd[2], 'x'))
875+
pset.popt.topt.expanded = 1;
876+
861877
switch (cmd[1])
862878
{
863879
case '\0':
@@ -873,13 +889,14 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
873889
{
874890
char *pattern2 = NULL;
875891

876-
if (pattern && cmd[2] != '\0' && cmd[2] != '+')
892+
if (pattern && cmd[2] != '\0' && cmd[2] != '+' && cmd[2] != 'x')
877893
pattern2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
878894

879895
switch (cmd[2])
880896
{
881897
case '\0':
882898
case '+':
899+
case 'x':
883900
success = describeAccessMethods(pattern, show_verbose);
884901
break;
885902
case 'c':
@@ -941,6 +958,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
941958
case 'p':
942959
case 't':
943960
case 'w':
961+
case 'x':
944962
success = exec_command_dfo(scan_state, cmd, pattern,
945963
show_verbose, show_system);
946964
break;
@@ -981,6 +999,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
981999
case 't':
9821000
case 'i':
9831001
case 'n':
1002+
case 'x':
9841003
success = listPartitionedTables(&cmd[2], pattern, show_verbose);
9851004
break;
9861005
default:
@@ -1041,6 +1060,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
10411060
{
10421061
case '\0':
10431062
case '+':
1063+
case 'x':
10441064
success = listTSConfigs(pattern, show_verbose);
10451065
break;
10461066
case 'p':
@@ -1093,6 +1113,9 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
10931113
status = PSQL_CMD_UNKNOWN;
10941114
}
10951115

1116+
/* Restore original expanded mode */
1117+
pset.popt.topt.expanded = save_expanded;
1118+
10961119
free(pattern);
10971120
}
10981121
else
@@ -2044,14 +2067,23 @@ exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd)
20442067
{
20452068
char *pattern;
20462069
bool show_verbose;
2070+
unsigned short int save_expanded;
20472071

20482072
pattern = psql_scan_slash_option(scan_state,
20492073
OT_NORMAL, NULL, true);
20502074

20512075
show_verbose = strchr(cmd, '+') ? true : false;
20522076

2077+
/* if 'x' option specified, force expanded mode */
2078+
save_expanded = pset.popt.topt.expanded;
2079+
if (strchr(cmd, 'x'))
2080+
pset.popt.topt.expanded = 1;
2081+
20532082
success = listAllDbs(pattern, show_verbose);
20542083

2084+
/* restore original expanded mode */
2085+
pset.popt.topt.expanded = save_expanded;
2086+
20552087
free(pattern);
20562088
}
20572089
else
@@ -2107,10 +2139,23 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
21072139
}
21082140
}
21092141

2110-
else if (strcmp(cmd + 3, "list") == 0)
2111-
success = listLargeObjects(false);
2112-
else if (strcmp(cmd + 3, "list+") == 0)
2113-
success = listLargeObjects(true);
2142+
else if (strncmp(cmd + 3, "list", 4) == 0)
2143+
{
2144+
bool show_verbose;
2145+
unsigned short int save_expanded;
2146+
2147+
show_verbose = strchr(cmd, '+') ? true : false;
2148+
2149+
/* if 'x' option specified, force expanded mode */
2150+
save_expanded = pset.popt.topt.expanded;
2151+
if (strchr(cmd, 'x'))
2152+
pset.popt.topt.expanded = 1;
2153+
2154+
success = listLargeObjects(show_verbose);
2155+
2156+
/* restore original expanded mode */
2157+
pset.popt.topt.expanded = save_expanded;
2158+
}
21142159

21152160
else if (strcmp(cmd + 3, "unlink") == 0)
21162161
{
@@ -3061,14 +3106,23 @@ exec_command_z(PsqlScanState scan_state, bool active_branch, const char *cmd)
30613106
{
30623107
char *pattern;
30633108
bool show_system;
3109+
unsigned short int save_expanded;
30643110

30653111
pattern = psql_scan_slash_option(scan_state,
30663112
OT_NORMAL, NULL, true);
30673113

30683114
show_system = strchr(cmd, 'S') ? true : false;
30693115

3116+
/* if 'x' option specified, force expanded mode */
3117+
save_expanded = pset.popt.topt.expanded;
3118+
if (strchr(cmd, 'x'))
3119+
pset.popt.topt.expanded = 1;
3120+
30703121
success = permissionsList(pattern, show_system);
30713122

3123+
/* restore original expanded mode */
3124+
pset.popt.topt.expanded = save_expanded;
3125+
30723126
free(pattern);
30733127
}
30743128
else

src/bin/psql/describe.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,9 @@ describeFunctions(const char *functypes, const char *func_pattern,
309309
/* No "Parallel" column before 9.6 */
310310
static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, true, false, false, false, false};
311311

312-
if (strlen(functypes) != strspn(functypes, "anptwS+"))
312+
if (strlen(functypes) != strspn(functypes, "anptwSx+"))
313313
{
314-
pg_log_error("\\df only takes [anptwS+] as options");
314+
pg_log_error("\\df only takes [anptwSx+] as options");
315315
return true;
316316
}
317317

src/bin/psql/help.c

+53-53
Original file line numberDiff line numberDiff line change
@@ -219,67 +219,67 @@ slashUsage(unsigned short int pager)
219219
HELP0("\n");
220220

221221
HELP0("Informational\n");
222-
HELP0(" (options: S = show system objects, + = additional detail)\n");
223-
HELP0(" \\d[S+] list tables, views, and sequences\n");
224-
HELP0(" \\d[S+] NAME describe table, view, sequence, or index\n");
225-
HELP0(" \\da[S] [PATTERN] list aggregates\n");
226-
HELP0(" \\dA[+] [PATTERN] list access methods\n");
227-
HELP0(" \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n");
228-
HELP0(" \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n");
229-
HELP0(" \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n");
230-
HELP0(" \\dAp[+] [AMPTRN [OPFPTRN]] list support functions of operator families\n");
231-
HELP0(" \\db[+] [PATTERN] list tablespaces\n");
232-
HELP0(" \\dc[S+] [PATTERN] list conversions\n");
233-
HELP0(" \\dconfig[+] [PATTERN] list configuration parameters\n");
234-
HELP0(" \\dC[+] [PATTERN] list casts\n");
235-
HELP0(" \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n");
236-
HELP0(" \\dD[S+] [PATTERN] list domains\n");
237-
HELP0(" \\ddp [PATTERN] list default privileges\n");
238-
HELP0(" \\dE[S+] [PATTERN] list foreign tables\n");
239-
HELP0(" \\des[+] [PATTERN] list foreign servers\n");
240-
HELP0(" \\det[+] [PATTERN] list foreign tables\n");
241-
HELP0(" \\deu[+] [PATTERN] list user mappings\n");
242-
HELP0(" \\dew[+] [PATTERN] list foreign-data wrappers\n");
243-
HELP0(" \\df[anptw][S+] [FUNCPTRN [TYPEPTRN ...]]\n"
222+
HELP0(" (options: S = show system objects, x = expanded mode, + = additional detail)\n");
223+
HELP0(" \\d[Sx+] list tables, views, and sequences\n");
224+
HELP0(" \\d[S+] NAME describe table, view, sequence, or index\n");
225+
HELP0(" \\da[Sx] [PATTERN] list aggregates\n");
226+
HELP0(" \\dA[x+] [PATTERN] list access methods\n");
227+
HELP0(" \\dAc[x+] [AMPTRN [TYPEPTRN]] list operator classes\n");
228+
HELP0(" \\dAf[x+] [AMPTRN [TYPEPTRN]] list operator families\n");
229+
HELP0(" \\dAo[x+] [AMPTRN [OPFPTRN]] list operators of operator families\n");
230+
HELP0(" \\dAp[x+] [AMPTRN [OPFPTRN]] list support functions of operator families\n");
231+
HELP0(" \\db[x+] [PATTERN] list tablespaces\n");
232+
HELP0(" \\dc[Sx+] [PATTERN] list conversions\n");
233+
HELP0(" \\dconfig[x+] [PATTERN] list configuration parameters\n");
234+
HELP0(" \\dC[x+] [PATTERN] list casts\n");
235+
HELP0(" \\dd[Sx] [PATTERN] show object descriptions not displayed elsewhere\n");
236+
HELP0(" \\dD[Sx+] [PATTERN] list domains\n");
237+
HELP0(" \\ddp[x] [PATTERN] list default privileges\n");
238+
HELP0(" \\dE[Sx+] [PATTERN] list foreign tables\n");
239+
HELP0(" \\des[x+] [PATTERN] list foreign servers\n");
240+
HELP0(" \\det[x+] [PATTERN] list foreign tables\n");
241+
HELP0(" \\deu[x+] [PATTERN] list user mappings\n");
242+
HELP0(" \\dew[x+] [PATTERN] list foreign-data wrappers\n");
243+
HELP0(" \\df[anptw][Sx+] [FUNCPTRN [TYPEPTRN ...]]\n"
244244
" list [only agg/normal/procedure/trigger/window] functions\n");
245-
HELP0(" \\dF[+] [PATTERN] list text search configurations\n");
246-
HELP0(" \\dFd[+] [PATTERN] list text search dictionaries\n");
247-
HELP0(" \\dFp[+] [PATTERN] list text search parsers\n");
248-
HELP0(" \\dFt[+] [PATTERN] list text search templates\n");
249-
HELP0(" \\dg[S+] [PATTERN] list roles\n");
250-
HELP0(" \\di[S+] [PATTERN] list indexes\n");
251-
HELP0(" \\dl[+] list large objects, same as \\lo_list\n");
252-
HELP0(" \\dL[S+] [PATTERN] list procedural languages\n");
253-
HELP0(" \\dm[S+] [PATTERN] list materialized views\n");
254-
HELP0(" \\dn[S+] [PATTERN] list schemas\n");
255-
HELP0(" \\do[S+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n"
245+
HELP0(" \\dF[x+] [PATTERN] list text search configurations\n");
246+
HELP0(" \\dFd[x+] [PATTERN] list text search dictionaries\n");
247+
HELP0(" \\dFp[x+] [PATTERN] list text search parsers\n");
248+
HELP0(" \\dFt[x+] [PATTERN] list text search templates\n");
249+
HELP0(" \\dg[Sx+] [PATTERN] list roles\n");
250+
HELP0(" \\di[Sx+] [PATTERN] list indexes\n");
251+
HELP0(" \\dl[x+] list large objects, same as \\lo_list\n");
252+
HELP0(" \\dL[Sx+] [PATTERN] list procedural languages\n");
253+
HELP0(" \\dm[Sx+] [PATTERN] list materialized views\n");
254+
HELP0(" \\dn[Sx+] [PATTERN] list schemas\n");
255+
HELP0(" \\do[Sx+] [OPPTRN [TYPEPTRN [TYPEPTRN]]]\n"
256256
" list operators\n");
257-
HELP0(" \\dO[S+] [PATTERN] list collations\n");
258-
HELP0(" \\dp[S] [PATTERN] list table, view, and sequence access privileges\n");
259-
HELP0(" \\dP[itn+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n");
260-
HELP0(" \\drds [ROLEPTRN [DBPTRN]] list per-database role settings\n");
261-
HELP0(" \\drg[S] [PATTERN] list role grants\n");
262-
HELP0(" \\dRp[+] [PATTERN] list replication publications\n");
263-
HELP0(" \\dRs[+] [PATTERN] list replication subscriptions\n");
264-
HELP0(" \\ds[S+] [PATTERN] list sequences\n");
265-
HELP0(" \\dt[S+] [PATTERN] list tables\n");
266-
HELP0(" \\dT[S+] [PATTERN] list data types\n");
267-
HELP0(" \\du[S+] [PATTERN] list roles\n");
268-
HELP0(" \\dv[S+] [PATTERN] list views\n");
269-
HELP0(" \\dx[+] [PATTERN] list extensions\n");
270-
HELP0(" \\dX [PATTERN] list extended statistics\n");
271-
HELP0(" \\dy[+] [PATTERN] list event triggers\n");
272-
HELP0(" \\l[+] [PATTERN] list databases\n");
273-
HELP0(" \\sf[+] FUNCNAME show a function's definition\n");
274-
HELP0(" \\sv[+] VIEWNAME show a view's definition\n");
275-
HELP0(" \\z[S] [PATTERN] same as \\dp\n");
257+
HELP0(" \\dO[Sx+] [PATTERN] list collations\n");
258+
HELP0(" \\dp[Sx] [PATTERN] list table, view, and sequence access privileges\n");
259+
HELP0(" \\dP[itnx+] [PATTERN] list [only index/table] partitioned relations [n=nested]\n");
260+
HELP0(" \\drds[x] [ROLEPTRN [DBPTRN]] list per-database role settings\n");
261+
HELP0(" \\drg[Sx] [PATTERN] list role grants\n");
262+
HELP0(" \\dRp[x+] [PATTERN] list replication publications\n");
263+
HELP0(" \\dRs[x+] [PATTERN] list replication subscriptions\n");
264+
HELP0(" \\ds[Sx+] [PATTERN] list sequences\n");
265+
HELP0(" \\dt[Sx+] [PATTERN] list tables\n");
266+
HELP0(" \\dT[Sx+] [PATTERN] list data types\n");
267+
HELP0(" \\du[Sx+] [PATTERN] list roles\n");
268+
HELP0(" \\dv[Sx+] [PATTERN] list views\n");
269+
HELP0(" \\dx[x+] [PATTERN] list extensions\n");
270+
HELP0(" \\dX[x] [PATTERN] list extended statistics\n");
271+
HELP0(" \\dy[x+] [PATTERN] list event triggers\n");
272+
HELP0(" \\l[x+] [PATTERN] list databases\n");
273+
HELP0(" \\sf[+] FUNCNAME show a function's definition\n");
274+
HELP0(" \\sv[+] VIEWNAME show a view's definition\n");
275+
HELP0(" \\z[Sx] [PATTERN] same as \\dp\n");
276276
HELP0("\n");
277277

278278
HELP0("Large Objects\n");
279279
HELP0(" \\lo_export LOBOID FILE write large object to file\n");
280280
HELP0(" \\lo_import FILE [COMMENT]\n"
281281
" read large object from file\n");
282-
HELP0(" \\lo_list[+] list large objects\n");
282+
HELP0(" \\lo_list[x+] list large objects\n");
283283
HELP0(" \\lo_unlink LOBOID delete a large object\n");
284284
HELP0("\n");
285285

0 commit comments

Comments
 (0)