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

Reply via email to