Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit169c8a9

Browse files
committed
psql: Support zero byte field and record separators
Add new psql settings and command-line options to support setting thefield and record separators for unaligned output to a zero byte, foreasier interfacing with other shell tools.reviewed by Abhijit Menon-Sen
1 parentdd7c841 commit169c8a9

File tree

6 files changed

+154
-46
lines changed

6 files changed

+154
-46
lines changed

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,27 @@ PostgreSQL documentation
482482
</listitem>
483483
</varlistentry>
484484

485+
<varlistentry>
486+
<term><option>-z</option></term>
487+
<term><option>--field-separator-zero</option></term>
488+
<listitem>
489+
<para>
490+
Set the field separator for unaligned output to a zero byte.
491+
</para>
492+
</listitem>
493+
</varlistentry>
494+
495+
<varlistentry>
496+
<term><option>-0</option></term>
497+
<term><option>--record-separator-zero</option></term>
498+
<listitem>
499+
<para>
500+
Set the record separator for unaligned output to a zero byte. This is
501+
useful for interfacing, for example, with <literal>xargs -0</literal>.
502+
</para>
503+
</listitem>
504+
</varlistentry>
505+
485506
<varlistentry>
486507
<term><option>-1</option></term>
487508
<term><option>--single-transaction</option></term>
@@ -1908,6 +1929,16 @@ lo_import 152801
19081929
</listitem>
19091930
</varlistentry>
19101931

1932+
<varlistentry>
1933+
<term><literal>fieldsep_zero</literal></term>
1934+
<listitem>
1935+
<para>
1936+
Sets the field separator to use in unaligned output format to a zero
1937+
byte.
1938+
</para>
1939+
</listitem>
1940+
</varlistentry>
1941+
19111942
<varlistentry>
19121943
<term><literal>footer</literal></term>
19131944
<listitem>
@@ -2077,6 +2108,16 @@ lo_import 152801
20772108
</listitem>
20782109
</varlistentry>
20792110

2111+
<varlistentry>
2112+
<term><literal>recordsep_zero</literal></term>
2113+
<listitem>
2114+
<para>
2115+
Sets the record separator to use in unaligned output format to a zero
2116+
byte.
2117+
</para>
2118+
</listitem>
2119+
</varlistentry>
2120+
20802121
<varlistentry>
20812122
<term><literal>tableattr</literal> (or <literal>T</literal>)</term>
20822123
<listitem>

‎src/bin/psql/command.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,30 +2272,57 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
22722272
{
22732273
if (value)
22742274
{
2275-
free(popt->topt.fieldSep);
2276-
popt->topt.fieldSep=pg_strdup(value);
2275+
free(popt->topt.fieldSep.separator);
2276+
popt->topt.fieldSep.separator=pg_strdup(value);
2277+
popt->topt.fieldSep.separator_zero= false;
22772278
}
22782279
if (!quiet)
2279-
printf(_("Field separator is \"%s\".\n"),popt->topt.fieldSep);
2280+
{
2281+
if (popt->topt.fieldSep.separator_zero)
2282+
printf(_("Field separator is zero byte.\n"));
2283+
else
2284+
printf(_("Field separator is \"%s\".\n"),popt->topt.fieldSep.separator);
2285+
}
2286+
}
2287+
2288+
elseif (strcmp(param,"fieldsep_zero")==0)
2289+
{
2290+
free(popt->topt.fieldSep.separator);
2291+
popt->topt.fieldSep.separator=NULL;
2292+
popt->topt.fieldSep.separator_zero= true;
2293+
if (!quiet)
2294+
printf(_("Field separator is zero byte.\n"));
22802295
}
22812296

22822297
/* record separator for unaligned text */
22832298
elseif (strcmp(param,"recordsep")==0)
22842299
{
22852300
if (value)
22862301
{
2287-
free(popt->topt.recordSep);
2288-
popt->topt.recordSep=pg_strdup(value);
2302+
free(popt->topt.recordSep.separator);
2303+
popt->topt.recordSep.separator=pg_strdup(value);
2304+
popt->topt.recordSep.separator_zero= false;
22892305
}
22902306
if (!quiet)
22912307
{
2292-
if (strcmp(popt->topt.recordSep,"\n")==0)
2308+
if (popt->topt.recordSep.separator_zero)
2309+
printf(_("Record separator is zero byte.\n"));
2310+
elseif (strcmp(popt->topt.recordSep.separator,"\n")==0)
22932311
printf(_("Record separator is <newline>."));
22942312
else
2295-
printf(_("Record separator is \"%s\".\n"),popt->topt.recordSep);
2313+
printf(_("Record separator is \"%s\".\n"),popt->topt.recordSep.separator);
22962314
}
22972315
}
22982316

2317+
elseif (strcmp(param,"recordsep_zero")==0)
2318+
{
2319+
free(popt->topt.recordSep.separator);
2320+
popt->topt.recordSep.separator=NULL;
2321+
popt->topt.recordSep.separator_zero= true;
2322+
if (!quiet)
2323+
printf(_("Record separator is zero byte.\n"));
2324+
}
2325+
22992326
/* toggle between full and tuples-only format */
23002327
elseif (strcmp(param,"t")==0||strcmp(param,"tuples_only")==0)
23012328
{

‎src/bin/psql/help.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ usage(void)
123123
printf(_(" -t, --tuples-only print rows only\n"));
124124
printf(_(" -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n"));
125125
printf(_(" -x, --expanded turn on expanded table output\n"));
126+
printf(_(" -z, --field-separator-zero\n"
127+
" set field separator to zero byte\n"));
128+
printf(_(" -0, --record-separator-zero\n"
129+
" set record separator to zero byte\n"));
126130

127131
printf(_("\nConnection options:\n"));
128132
/* Display default host */
@@ -237,8 +241,8 @@ slashUsage(unsigned short int pager)
237241
fprintf(output,_(" \\H toggle HTML output mode (currently %s)\n"),
238242
ON(pset.popt.topt.format==PRINT_HTML));
239243
fprintf(output,_(" \\pset NAME [VALUE] set table output option\n"
240-
" (NAME := {format|border|expanded|fieldsep|footer|null|\n"
241-
" numericlocale|recordsep|tuples_only|title|tableattr|pager})\n"));
244+
" (NAME := {format|border|expanded|fieldsep|fieldsep_zero|footer|null|\n"
245+
" numericlocale|recordsep|recordsep_zero|tuples_only|title|tableattr|pager})\n"));
242246
fprintf(output,_(" \\t [on|off] show only rows (currently %s)\n"),
243247
ON(pset.popt.topt.tuples_only));
244248
fprintf(output,_(" \\T [STRING] set HTML <table> tag attributes, or unset if none\n"));

‎src/bin/psql/print.c

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,16 @@ fputnbytes(FILE *f, const char *str, size_t n)
268268
}
269269

270270

271+
staticvoid
272+
print_separator(structseparatorsep,FILE*fout)
273+
{
274+
if (sep.separator_zero)
275+
fputc('\000',fout);
276+
elseif (sep.separator)
277+
fputs(sep.separator,fout);
278+
}
279+
280+
271281
/*************************/
272282
/* Unaligned text */
273283
/*************************/
@@ -276,8 +286,6 @@ fputnbytes(FILE *f, const char *str, size_t n)
276286
staticvoid
277287
print_unaligned_text(constprintTableContent*cont,FILE*fout)
278288
{
279-
constchar*opt_fieldsep=cont->opt->fieldSep;
280-
constchar*opt_recordsep=cont->opt->recordSep;
281289
boolopt_tuples_only=cont->opt->tuples_only;
282290
unsignedinti;
283291
constchar*const*ptr;
@@ -286,24 +294,22 @@ print_unaligned_text(const printTableContent *cont, FILE *fout)
286294
if (cancel_pressed)
287295
return;
288296

289-
if (!opt_fieldsep)
290-
opt_fieldsep="";
291-
if (!opt_recordsep)
292-
opt_recordsep="";
293-
294297
if (cont->opt->start_table)
295298
{
296299
/* print title */
297300
if (!opt_tuples_only&&cont->title)
298-
fprintf(fout,"%s%s",cont->title,opt_recordsep);
301+
{
302+
fputs(cont->title,fout);
303+
print_separator(cont->opt->recordSep,fout);
304+
}
299305

300306
/* print headers */
301307
if (!opt_tuples_only)
302308
{
303309
for (ptr=cont->headers;*ptr;ptr++)
304310
{
305311
if (ptr!=cont->headers)
306-
fputs(opt_fieldsep,fout);
312+
print_separator(cont->opt->fieldSep,fout);
307313
fputs(*ptr,fout);
308314
}
309315
need_recordsep= true;
@@ -318,15 +324,15 @@ print_unaligned_text(const printTableContent *cont, FILE *fout)
318324
{
319325
if (need_recordsep)
320326
{
321-
fputs(opt_recordsep,fout);
327+
print_separator(cont->opt->recordSep,fout);
322328
need_recordsep= false;
323329
if (cancel_pressed)
324330
break;
325331
}
326332
fputs(*ptr,fout);
327333

328334
if ((i+1) %cont->ncolumns)
329-
fputs(opt_fieldsep,fout);
335+
print_separator(cont->opt->fieldSep,fout);
330336
else
331337
need_recordsep= true;
332338
}
@@ -342,25 +348,32 @@ print_unaligned_text(const printTableContent *cont, FILE *fout)
342348
{
343349
if (need_recordsep)
344350
{
345-
fputs(opt_recordsep,fout);
351+
print_separator(cont->opt->recordSep,fout);
346352
need_recordsep= false;
347353
}
348354
fputs(f->data,fout);
349355
need_recordsep= true;
350356
}
351357
}
352-
/* the last record needs to be concluded with a newline */
358+
/*
359+
* The last record is terminated by a newline, independent of the set
360+
* record separator. But when the record separator is a zero byte, we
361+
* use that (compatible with find -print0 and xargs).
362+
*/
353363
if (need_recordsep)
354-
fputc('\n',fout);
364+
{
365+
if (cont->opt->recordSep.separator_zero)
366+
print_separator(cont->opt->recordSep,fout);
367+
else
368+
fputc('\n',fout);
369+
}
355370
}
356371
}
357372

358373

359374
staticvoid
360375
print_unaligned_vertical(constprintTableContent*cont,FILE*fout)
361376
{
362-
constchar*opt_fieldsep=cont->opt->fieldSep;
363-
constchar*opt_recordsep=cont->opt->recordSep;
364377
boolopt_tuples_only=cont->opt->tuples_only;
365378
unsignedinti;
366379
constchar*const*ptr;
@@ -369,11 +382,6 @@ print_unaligned_vertical(const printTableContent *cont, FILE *fout)
369382
if (cancel_pressed)
370383
return;
371384

372-
if (!opt_fieldsep)
373-
opt_fieldsep="";
374-
if (!opt_recordsep)
375-
opt_recordsep="";
376-
377385
if (cont->opt->start_table)
378386
{
379387
/* print title */
@@ -393,19 +401,19 @@ print_unaligned_vertical(const printTableContent *cont, FILE *fout)
393401
if (need_recordsep)
394402
{
395403
/* record separator is 2 occurrences of recordsep in this mode */
396-
fputs(opt_recordsep,fout);
397-
fputs(opt_recordsep,fout);
404+
print_separator(cont->opt->recordSep,fout);
405+
print_separator(cont->opt->recordSep,fout);
398406
need_recordsep= false;
399407
if (cancel_pressed)
400408
break;
401409
}
402410

403411
fputs(cont->headers[i %cont->ncolumns],fout);
404-
fputs(opt_fieldsep,fout);
412+
print_separator(cont->opt->fieldSep,fout);
405413
fputs(*ptr,fout);
406414

407415
if ((i+1) %cont->ncolumns)
408-
fputs(opt_recordsep,fout);
416+
print_separator(cont->opt->recordSep,fout);
409417
else
410418
need_recordsep= true;
411419
}
@@ -417,15 +425,19 @@ print_unaligned_vertical(const printTableContent *cont, FILE *fout)
417425
{
418426
printTableFooter*f;
419427

420-
fputs(opt_recordsep,fout);
428+
print_separator(cont->opt->recordSep,fout);
421429
for (f=cont->footers;f;f=f->next)
422430
{
423-
fputs(opt_recordsep,fout);
431+
print_separator(cont->opt->recordSep,fout);
424432
fputs(f->data,fout);
425433
}
426434
}
427435

428-
fputc('\n',fout);
436+
/* see above in print_unaligned_text() */
437+
if (cont->opt->recordSep.separator_zero)
438+
print_separator(cont->opt->recordSep,fout);
439+
else
440+
fputc('\n',fout);
429441
}
430442
}
431443

‎src/bin/psql/print.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ typedef struct printTextFormat
6767
* marks when border=0? */
6868
}printTextFormat;
6969

70+
structseparator
71+
{
72+
char*separator;
73+
boolseparator_zero;
74+
};
75+
7076
typedefstructprintTableOpt
7177
{
7278
enumprintFormatformat;/* see enum above */
@@ -81,8 +87,8 @@ typedef struct printTableOpt
8187
boolstop_table;/* print stop decoration, eg </table> */
8288
unsigned longprior_records;/* start offset for record counters */
8389
constprintTextFormat*line_style;/* line style (NULL for default) */
84-
char*fieldSep;/* field separator for unaligned text mode */
85-
char*recordSep;/* record separator for unaligned text mode */
90+
structseparatorfieldSep;/* field separator for unaligned text mode */
91+
structseparatorrecordSep;/* record separator for unaligned text mode */
8692
boolnumericLocale;/* locale-aware numeric units separator and
8793
* decimal marker */
8894
char*tableAttr;/* attributes for HTML <table ...> */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp