psql_column_filter.diff
text/x-patch
Filename: psql_column_filter.diff
Type: text/x-patch
Part: 0
Message:
Re: psql: add \pset true/false
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/bin/psql/command.c | 24 | 1 |
| src/bin/psql/print.c | 89 | 2 |
| src/bin/psql/print.h | 1 | 0 |
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 438a4ec..5dad70b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1148,7 +1148,8 @@ exec_command(const char *cmd,
int i;
static const char *const my_list[] = {
- "border", "columns", "expanded", "fieldsep", "fieldsep_zero",
+ "border", "columns", "column_filter",
+ "expanded", "fieldsep", "fieldsep_zero",
"footer", "format", "linestyle", "null",
"numericlocale", "pager", "pager_min_lines",
"recordsep", "recordsep_zero",
@@ -2695,6 +2696,17 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
if (value)
popt->topt.columns = atoi(value);
}
+ /* set column filter */
+ else if (strcmp(param, "columnfilter") == 0)
+ {
+ if (vallen > 0)
+ popt->topt.columnfilter = pg_strdup(value);
+ else
+ {
+ if (popt->topt.columnfilter) pg_free(popt->topt.columnfilter);
+ popt->topt.columnfilter = NULL;
+ }
+ }
else
{
psql_error("\\pset: unknown option: %s\n", param);
@@ -2726,6 +2738,15 @@ printPsetInfo(const char *param, struct printQueryOpt *popt)
printf(_("Target width is %d.\n"), popt->topt.columns);
}
+ /* show the target width for the wrapped format */
+ else if (strcmp(param, "columnfilter") == 0)
+ {
+ if (!popt->topt.columnfilter)
+ printf(_("Column filter is unset.\n"));
+ else
+ printf(_("Column filter is \"%s\".\n"), popt->topt.columnfilter);
+ }
+
/* show expanded/vertical mode */
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
{
@@ -2938,6 +2959,8 @@ pset_value_string(const char *param, struct printQueryOpt *popt)
return psprintf("%d", popt->topt.border);
else if (strcmp(param, "columns") == 0)
return psprintf("%d", popt->topt.columns);
+ else if (strcmp(param, "columnfilter") == 0)
+ return pstrdup(popt->topt.columnfilter);
else if (strcmp(param, "expanded") == 0)
return pstrdup(popt->topt.expanded == 2
? "auto"
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index ad4350e..9731e54 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -195,7 +195,7 @@ static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,
FILE **fout, bool *is_pager);
static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
-
+static char *valfilter(char *filtname, char *origcell, int colnum, int type, bool *mustfree);
/* Count number of digits in integral part of number */
static int
@@ -3145,6 +3145,86 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
ClosePager(fout);
}
+static char *
+valfilter(char *filtname, char *origcell, int colnum, int type, bool *mustfree)
+{
+ char *cmdline;
+ int buflen = strlen(filtname) + 1 +
+ log10(colnum > 0 ? colnum : 1) + 2 + log10(type) + 2 +
+ + strlen(origcell) + 1 ;
+ FILE *fp;
+ size_t celllen;
+ char *newcell = NULL;
+ char *p;
+ int additional_bytes;
+ bool escape_needed = false;
+
+ /* Check necessity of escaping */
+ for (additional_bytes = 0, p = origcell ; *p ; p++)
+ {
+ if (*p == '\'')
+ {
+ additional_bytes += 4; /* strlen('"'"') - 1 */
+ escape_needed = true;
+ }
+ else if (*p == ' ')
+ escape_needed = true;
+ }
+
+ /* Escaping needed */
+ if (escape_needed)
+ {
+ char *q;
+ char *str;
+ int newlen;
+
+ additional_bytes += 2;
+ newlen = strlen(origcell) + 1 + additional_bytes;
+ str = (char *)pg_malloc(newlen);
+
+ q = str;
+ *q++ = '\'';
+ for (p = origcell ; *p ; p++)
+ {
+ if (*p == '\'')
+ {
+ strcpy(q, "'\"'\"'");
+ q += 5;
+ }
+ else
+ *q++ = *p;
+ }
+ *q++ = '\'';
+ *q++ = '\0';
+ Assert(q - str == newlen);
+
+ if(*mustfree) free(origcell);
+ origcell = str;
+ *mustfree = true;
+ buflen += additional_bytes;
+ }
+
+ cmdline = pg_malloc(buflen);
+ snprintf(cmdline, buflen, "%s %d %d %s", filtname, type, colnum, origcell);
+ fp = popen(cmdline, "r");
+
+ /* fail silently */
+ if (!fp) return origcell;
+
+
+ /* receive the result from the filter */
+ if (*mustfree) free(origcell);
+ getline(&newcell, &celllen, fp); /* POSIX 2008 */
+ fclose(fp);
+ pg_free(cmdline);
+
+ /* chop newlines */
+ for (p = newcell ; *p && *p != '\n' && *p != '\r' ; p++);
+ *p = 0;
+ *mustfree = true;
+ return newcell;
+}
+
/*
* Use this to print query results
*
@@ -3209,7 +3289,14 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
cell = opt->nullPrint ? opt->nullPrint : "";
else
{
- cell = PQgetvalue(result, r, c);
+ /* This filter is quite slow */
+ if (opt->topt.columnfilter)
+ cell = valfilter(opt->topt.columnfilter,
+ PQgetvalue(result, r, c),
+ c,
+ PQftype(result, c),
+ &mustfree);
+
if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
{
cell = format_numeric_locale(cell);
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index b0b6bf5..5f2e2b3 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -109,6 +109,7 @@ typedef struct printTableOpt
unicode_linestyle unicode_border_linestyle;
unicode_linestyle unicode_column_linestyle;
unicode_linestyle unicode_header_linestyle;
+ char *columnfilter; /* the name of column filter program*/
} printTableOpt;
/*