Some new SPI functions - Mailing list pgsql-patches

From Thomas Hallgren
Subject Some new SPI functions
Date
Msg-id c0fpeq$16hm$1@news.hub.org
Whole thread Raw
Responses Re: Some new SPI functions
Re: Some new SPI functions
List pgsql-patches
I need three new functions in the Server Programming Interface (SPI) when
mapping an ExecutionPlan to a Java prepared statement (Pl/Java project).


The execute method of the prepared statement needs to know if the result is
a ResultSet (SPI_cursor_open) or just a number indicated how many rows that
where affected (SPI_execp). Currently there's no way I can tell by just
looking at the plan unless I violate the data hiding and use spi_priv.h. I
really don't want to do that. Hence the need for SPI_is_cursor_plan

I send an array of java objects for the arguments. The
SPI_cursor_open/SPI_execp of course expects the arguments to be Datum's and
the mapper must convert java objects. The mapping code is based on Oid's so
I need a way to extract the number of expected arguments and the typeid of
each arguments.

I find it likely that other pl<lang> implementations where similar support
is planned might find these functions useful.


Thomas Hallgren

Index: src/backend/executor/spi.c
===================================================================
retrieving revision 1.109
diff -u -r1.109 spi.c
--- src/backend/executor/spi.c 2 Dec 2003 19:26:47 -0000 1.109
+++ src/backend/executor/spi.c 12 Feb 2004 11:13:11 -0000
@@ -918,6 +918,65 @@
  PortalDrop(portal, false);
 }

+/*
+ * Returns the Oid representing the type id for argument at argIndex. First
+ * parameter is at index zero.
+ */
+Oid
+SPI_getargtypeid(void *plan, int argIndex)
+{
+ if (plan == NULL || argIndex < 0 || argIndex >= ((_SPI_plan*)plan)->nargs)
+ {
+  SPI_result = SPI_ERROR_ARGUMENT;
+  return InvalidOid;
+ }
+ return ((_SPI_plan *) plan)->argtypes[argIndex];
+}
+
+/*
+ * Returns the number of arguments for the prepared plan.
+ */
+int
+SPI_getargcount(void *plan)
+{
+ if (plan == NULL)
+ {
+  SPI_result = SPI_ERROR_ARGUMENT;
+  return -1;
+ }
+ return ((_SPI_plan *) plan)->nargs;
+}
+
+/*
+ * Returns true if the plan contains exactly one command
+ * and that command originates from normal SELECT (i.e.
+ * *not* a SELECT ... INTO). In essence, the result indicates
+ * if the command can be used with SPI_cursor_open
+ *
+ * Parameters
+ *    plan A plan previously prepared using SPI_prepare
+ */
+bool
+SPI_is_cursor_plan(void *plan)
+{
+ List *qtlist;
+ _SPI_plan *spiplan = (_SPI_plan *) plan;
+ if (spiplan == NULL)
+ {
+  SPI_result = SPI_ERROR_ARGUMENT;
+  return false;
+ }
+
+ qtlist = spiplan->qtlist;
+ if(length(spiplan->ptlist) == 1 && length(qtlist) == 1)
+ {
+  Query *queryTree = (Query *) lfirst((List *) lfirst(qtlist));
+  if(queryTree->commandType == CMD_SELECT && queryTree->into == NULL)
+   return true;
+ }
+ return false;
+}
+
 /* =================== private functions =================== */

 /*
Index: src/include/executor/spi.h
===================================================================
retrieving revision 1.41
diff -u -r1.41 spi.h
--- src/include/executor/spi.h 2 Dec 2003 19:26:47 -0000 1.41
+++ src/include/executor/spi.h 12 Feb 2004 11:13:21 -0000
@@ -90,6 +90,10 @@
 extern void *SPI_saveplan(void *plan);
 extern int SPI_freeplan(void *plan);

+extern Oid SPI_getargtypeid(void *plan, int argIndex);
+extern int SPI_getargcount(void *plan);
+extern bool SPI_is_cursor_plan(void *plan);
+
 extern HeapTuple SPI_copytuple(HeapTuple tuple);
 extern TupleDesc SPI_copytupledesc(TupleDesc tupdesc);
 extern TupleTableSlot *SPI_copytupleintoslot(HeapTuple tuple,



pgsql-patches by date:

Previous
From: "Thomas Hallgren"
Date:
Subject: Re: Calling a java program thru a trigger or a function in postgresql
Next
From: Tom Lane
Date:
Subject: Re: Some new SPI functions