Hello, the attched is an example implement of output filter
dynamic loading feature of psql.
At Thu, 3 Dec 2015 10:41:11 +0900, Michael Paquier <[email protected]>
wrote in <cab7npqsulvd0m8gwkl2bar4suxrwy2+ybymtbm0ut4at7jg...@mail.gmail.com>
> > How about plugins on psql side? Calling hooked function in
> > printQuery could do that on psql. Impact on psql itself is
> > minimized. (Of course code for loading is omitted in the below
> > but it would also small...)
>
> That's interesting, and crazy. You would basically need to have the
> equivalent of \load, or an environment variable like PSQL_SHARED_LIBS
> that is similar to shared_preload_libraries on client-side. In short I
> guess that's actually a clone of LD_PRELOAD.
It is bothersome to share the server-side preload feature so I
made this as a minimal implement. Some safety meature should be
added but not so severe than backend. I home this is an
acceptable mess.
The attached patch adds a function to load output filter DLL.
The second file is an example filter module. The following
commandline with the file can create a test filter module. I
suppose preload feature only needs additional few lines.
gcc -I<pgsql_include> -fPIC -shared outfunctest.c -o /tmp/outfunctest.so
Then, on psql command line.
=# select 't'::bool;
bool
------
t
=# \load_dll /tmp/outfunctest.so
=# select 't'::bool;
bool
-----------
TRRRRUEEE
(1 row)
Anyone can tweak any type of output by this.
Opinions, suggestions or rejections are welcome.
regards,
--
Kyotaro Horiguchi
NTT Open Source Software Center
>From ac5e917a1bd802c37e56dc0861adb8807126d2eb Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <[email protected]>
Date: Thu, 3 Dec 2015 14:38:03 +0900
Subject: [PATCH] Test implement of dynamic-loadable output filter.
This is a minimum implement so that psql can dynamically load output
filter module. As a test code, this can load only by slash command, no
unload or reload or preloasd feature.
---
src/bin/psql/Makefile | 2 +-
src/bin/psql/command.c | 8 ++++++++
src/bin/psql/print.c | 6 ++++++
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/bin/psql/Makefile b/src/bin/psql/Makefile
index f1336d5..2fb1fd1 100644
--- a/src/bin/psql/Makefile
+++ b/src/bin/psql/Makefile
@@ -23,7 +23,7 @@ override CPPFLAGS := -I. -I$(srcdir) -I$(libpq_srcdir) -I$(top_srcdir)/src/bin/p
OBJS= command.o common.o help.o input.o stringutils.o mainloop.o copy.o \
startup.o prompt.o variables.o large_obj.o print.o describe.o \
tab-complete.o mbprint.o dumputils.o keywords.o kwlookup.o \
- sql_help.o \
+ sql_help.o dlload.o\
$(WIN32RES)
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 438a4ec..4101d99 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -40,6 +40,7 @@
#include "common.h"
#include "copy.h"
#include "describe.h"
+#include "dlload.h"
#include "help.h"
#include "input.h"
#include "large_obj.h"
@@ -1001,6 +1002,13 @@ exec_command(const char *cmd,
free(opt2);
}
+ else if (strcmp(cmd, "load_dll") == 0)
+ {
+ char *opt1 = psql_scan_slash_option(scan_state,
+ OT_NORMAL, NULL, true);
+ expand_tilde(&opt1);
+ success = do_dlload(opt1);
+ }
/* \o -- set query output */
else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index ad4350e..37febb2 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -27,6 +27,7 @@
#include "common.h"
#include "mbprint.h"
#include "print.h"
+#include "dlload.h"
/*
* We define the cancel_pressed flag in this file, rather than common.c where
@@ -3210,6 +3211,11 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
else
{
cell = PQgetvalue(result, r, c);
+
+ /* Call output filter if registered */
+ if (outputfilter)
+ cell = outputfilter(cell, PQftype(result, c), (&mustfree));
+
if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
{
cell = format_numeric_locale(cell);
--
1.8.3.1
#include <stdlib.h>
#include "postgres_fe.h"
#include "catalog/pg_type.h"
char *
outputfilter(char *origcell, int type, bool *mustfree)
{
char *retcell;
switch (type)
{
case BOOLOID:
retcell = (*origcell == 't' ? "TRRRRUEEE" : "FAAALSE");
if (*mustfree) free(origcell);
*mustfree = false;
break;
default:
retcell = origcell;
break;
}
return retcell;
}
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers