Select parser at runtime

From: Ian Lance Taylor <ian(at)airs(dot)com>
To: pgsql-patches(at)postgresql(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Select parser at runtime
Date: 2001-08-11 01:05:30
Message-ID: siu1zf4d9h.fsf@daffy.airs.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches

I've been experimenting with using a different parser (one which is
more Oracle compatible). While the parser is not yet ready for prime
time, I thought I would send out the code used to select the parser to
gauge its level of acceptability. If this patch isn't going to fly,
then my approach to an alternate parser isn't going to fly either.

After this patch is applied, you can switch to a new parser by doing
something like this:

create function my_parser(opaque, opaque, opaque) returns opaque
as '..../parser.so' language 'c';
set parser = my_parser;

After you do this, all subsequent input will be interpreted using the
specified parser. Note that you may want to leave yourself an escape
hatch of some sort to set the parser back to Postgres standard.

If this patch is accepted, then some further work needs to be done to
set the parser for SPI calls, so that it is possible for the user to
change the parser while still using ordinary PL/pgSQL.

I would appreciate any feedback.

Ian

Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/tcop/postgres.c,v
retrieving revision 1.230
diff -u -r1.230 postgres.c
--- src/backend/tcop/postgres.c 2001/08/04 00:14:43 1.230
+++ src/backend/tcop/postgres.c 2001/08/11 00:53:08
@@ -58,9 +58,11 @@
#include "tcop/utility.h"
#include "storage/proc.h"
#include "utils/exc.h"
+#include "utils/fcache.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
+#include "utils/syscache.h"
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
#endif
@@ -118,6 +120,10 @@
*/
int XfuncMode = 0;

+char *parser_function_name = 0;
+static bool update_parser_function_fcache = true;
+static FunctionCachePtr parser_function_fcache = NULL;
+
/* ----------------------------------------------------------------
* decls for routines only used in this file
* ----------------------------------------------------------------
@@ -389,8 +395,23 @@

if (Show_parser_stats)
ResetUsage();
+
+ if (update_parser_function_fcache)
+ assign_parser(parser_function_name);
+
+ if (parser_function_fcache == NULL)
+ raw_parsetree_list = parser(query_string, typev, nargs);
+ else
+ {
+ Datum result;
+
+ parser_function_fcache->fcinfo.arg[0] = PointerGetDatum(query_string);
+ parser_function_fcache->fcinfo.arg[1] = PointerGetDatum(typev);
+ parser_function_fcache->fcinfo.arg[2] = Int32GetDatum(nargs);

- raw_parsetree_list = parser(query_string, typev, nargs);
+ result = FunctionCallInvoke(&parser_function_fcache->fcinfo);
+ raw_parsetree_list = (List *) DatumGetPointer(result);
+ }

if (Show_parser_stats)
{
@@ -399,6 +420,82 @@
}

return raw_parsetree_list;
+}
+
+/*
+ * Check that we can find a parser function. This is called when the
+ * user assigns a value to the `parser' variable.
+ */
+bool
+check_parser(const char *proposed)
+{
+ HeapTuple tup;
+ Oid argtypes[FUNC_MAX_ARGS];
+
+ if (proposed[0] == '\0' || strcmp(proposed, "postgres") == 0)
+ return true;
+
+ /* We can't check this unless we have started running. */
+ if (! IsNormalProcessingMode())
+ return true;
+
+ memset(argtypes, 0, sizeof argtypes);
+ tup = SearchSysCache(PROCNAME,
+ PointerGetDatum(proposed),
+ Int32GetDatum(3),
+ PointerGetDatum(argtypes),
+ 0);
+ if (! HeapTupleIsValid(tup))
+ return false;
+ ReleaseSysCache(tup);
+ return true;
+}
+
+/*
+ * Assign a new parser function.
+ */
+void
+assign_parser(const char *value)
+{
+ FunctionCachePtr fcache;
+ HeapTuple tup;
+ Oid argtypes[FUNC_MAX_ARGS];
+ Oid oid;
+
+ /* We can't update parser_function_fcache until we have started
+ * running.
+ */
+ if (! IsNormalProcessingMode())
+ {
+ update_parser_function_fcache = true;
+ return;
+ }
+
+ if (value[0] == '\0' || strcmp(value, "postgres") == 0)
+ fcache = NULL;
+ else
+ {
+ memset(argtypes, 0, sizeof argtypes);
+ tup = SearchSysCache(PROCNAME,
+ PointerGetDatum(value),
+ Int32GetDatum(3),
+ PointerGetDatum(argtypes),
+ 0);
+ if (! HeapTupleIsValid(tup))
+ elog(ERROR, "parser function %s does not exist", value);
+
+ oid = tup->t_data->t_oid;
+
+ ReleaseSysCache(tup);
+
+ fcache = init_fcache(oid, 3, TopMemoryContext);
+ }
+
+ if (parser_function_fcache != NULL)
+ pfree(parser_function_fcache);
+ parser_function_fcache = fcache;
+
+ update_parser_function_fcache = false;
}

/*
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.45
diff -u -r1.45 guc.c
--- src/backend/utils/misc/guc.c 2001/07/05 15:19:40 1.45
+++ src/backend/utils/misc/guc.c 2001/08/11 00:53:11
@@ -376,6 +376,9 @@
{"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile,
PG_KRB_SRVTAB, NULL, NULL},

+ {"parser", PGC_USERSET, &parser_function_name, "",
+ check_parser, assign_parser},
+
#ifdef ENABLE_SYSLOG
{"syslog_facility", PGC_POSTMASTER, &Syslog_facility,
"LOCAL0", check_facility, NULL},
Index: src/include/tcop/tcopprot.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/tcop/tcopprot.h,v
retrieving revision 1.41
diff -u -r1.41 tcopprot.h
--- src/include/tcop/tcopprot.h 2001/06/08 21:16:48 1.41
+++ src/include/tcop/tcopprot.h 2001/08/11 00:53:12
@@ -31,6 +31,8 @@
extern bool HostnameLookup;
extern bool ShowPortNumber;

+extern char *parser_function_name;
+
#ifndef BOOTSTRAP_INCLUDE

extern List *pg_parse_and_rewrite(char *query_string,
@@ -39,6 +41,8 @@
extern void pg_exec_query_string(char *query_string,
CommandDest dest,
MemoryContext parse_context);
+extern bool check_parser(const char *proposed);
+extern void assign_parser(const char *value);

#endif /* BOOTSTRAP_INCLUDE */

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message P. Dwayne Miller 2001-08-11 01:53:28 Re: Bug?
Previous Message Tom Lane 2001-08-11 00:53:49 Re: Bug?

Browse pgsql-patches by date

  From Date Subject
Next Message Tom Lane 2001-08-11 15:50:30 Re: Select parser at runtime
Previous Message Mikhail Terekhov 2001-08-10 22:52:24 libpgtcl for tcl >= 8.0 (Unix & Windows)