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 <michael.paqu...@gmail.com> 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 <horiguchi.kyot...@lab.ntt.co.jp> 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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers