1998-08-22 14:38:39 +02:00
|
|
|
/**********************************************************************
|
|
|
|
* pl_handler.c - Handler for the PL/pgSQL
|
|
|
|
* procedural language
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2000-05-28 19:56:29 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.4 2000/05/28 17:56:28 tgl Exp $
|
1998-08-22 14:38:39 +02:00
|
|
|
*
|
1998-09-01 06:40:42 +02:00
|
|
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
1998-08-22 14:38:39 +02:00
|
|
|
*
|
1998-09-01 06:40:42 +02:00
|
|
|
* The author hereby grants permission to use, copy, modify,
|
|
|
|
* distribute, and license this software and its documentation
|
|
|
|
* for any purpose, provided that existing copyright notices are
|
|
|
|
* retained in all copies and that this notice is included
|
|
|
|
* verbatim in any distributions. No written agreement, license,
|
|
|
|
* or royalty fee is required for any of the authorized uses.
|
|
|
|
* Modifications to this software may be copyrighted by their
|
|
|
|
* author and need not follow the licensing terms described
|
|
|
|
* here, provided that the new terms are clearly indicated on
|
|
|
|
* the first page of each file where they apply.
|
1998-08-22 14:38:39 +02:00
|
|
|
*
|
1998-09-01 06:40:42 +02:00
|
|
|
* IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
|
|
|
|
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
|
|
|
|
* IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
|
|
* DAMAGE.
|
1998-08-22 14:38:39 +02:00
|
|
|
*
|
1998-09-01 06:40:42 +02:00
|
|
|
* THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
|
|
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
|
|
|
|
* AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
|
|
|
|
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
|
|
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
1998-08-22 14:38:39 +02:00
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "plpgsql.h"
|
|
|
|
#include "pl.tab.h"
|
|
|
|
|
|
|
|
#include "access/heapam.h"
|
|
|
|
#include "catalog/pg_proc.h"
|
|
|
|
#include "catalog/pg_type.h"
|
2000-05-28 19:56:29 +02:00
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/syscache.h"
|
1998-08-22 14:38:39 +02:00
|
|
|
|
|
|
|
|
2000-05-28 19:56:29 +02:00
|
|
|
/*
|
|
|
|
* Head of list of already-compiled functions
|
|
|
|
*/
|
1998-09-01 06:40:42 +02:00
|
|
|
static PLpgSQL_function *compiled_functions = NULL;
|
1998-08-22 14:38:39 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* ----------
|
2000-05-28 19:56:29 +02:00
|
|
|
* plpgsql_call_handler
|
|
|
|
*
|
|
|
|
* This is the only visible function of the PL interpreter.
|
|
|
|
* The PostgreSQL function manager and trigger manager
|
|
|
|
* call this function for execution of PL/pgSQL procedures.
|
1998-08-22 14:38:39 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
Datum
|
2000-05-28 19:56:29 +02:00
|
|
|
plpgsql_call_handler(PG_FUNCTION_ARGS)
|
1998-08-22 14:38:39 +02:00
|
|
|
{
|
2000-05-28 19:56:29 +02:00
|
|
|
TriggerData *trigdata;
|
|
|
|
bool isTrigger;
|
|
|
|
PLpgSQL_function *func;
|
1998-09-01 06:40:42 +02:00
|
|
|
Datum retval;
|
|
|
|
|
|
|
|
/* ----------
|
2000-05-28 19:56:29 +02:00
|
|
|
* Save the current trigger data local
|
|
|
|
*
|
|
|
|
* XXX this should go away in favor of using fcinfo->context
|
1998-09-01 06:40:42 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2000-05-28 19:56:29 +02:00
|
|
|
trigdata = CurrentTriggerData;
|
|
|
|
CurrentTriggerData = NULL;
|
|
|
|
isTrigger = (trigdata != NULL);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
|
|
|
/* ----------
|
2000-05-28 19:56:29 +02:00
|
|
|
* Connect to SPI manager
|
1998-09-01 06:40:42 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2000-05-28 19:56:29 +02:00
|
|
|
if (SPI_connect() != SPI_OK_CONNECT)
|
|
|
|
elog(ERROR, "plpgsql: cannot connect to SPI manager");
|
1998-09-01 06:40:42 +02:00
|
|
|
|
|
|
|
/* ----------
|
2000-05-28 19:56:29 +02:00
|
|
|
* Check if we already compiled this function and saved the pointer
|
|
|
|
* (ie, current FmgrInfo has been used before)
|
1998-09-01 06:40:42 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2000-05-28 19:56:29 +02:00
|
|
|
func = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
|
1998-09-01 06:40:42 +02:00
|
|
|
if (func == NULL)
|
|
|
|
{
|
2000-05-28 19:56:29 +02:00
|
|
|
/* ----------
|
|
|
|
* Check if we already compiled this function
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
Oid funcOid = fcinfo->flinfo->fn_oid;
|
|
|
|
|
|
|
|
for (func = compiled_functions; func != NULL; func = func->next)
|
|
|
|
{
|
|
|
|
if (funcOid == func->fn_oid)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* If not, do so and add it to the compiled ones
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
if (func == NULL)
|
|
|
|
{
|
|
|
|
func = plpgsql_compile(funcOid,
|
|
|
|
isTrigger ? T_TRIGGER : T_FUNCTION);
|
|
|
|
func->next = compiled_functions;
|
|
|
|
compiled_functions = func;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------
|
|
|
|
* Save pointer in FmgrInfo to avoid search on subsequent calls
|
|
|
|
* ----------
|
|
|
|
*/
|
|
|
|
fcinfo->flinfo->fn_extra = (void *) func;
|
1998-09-01 06:40:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------
|
2000-05-28 19:56:29 +02:00
|
|
|
* Determine if called as function or trigger and
|
|
|
|
* call appropriate subhandler
|
1998-09-01 06:40:42 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2000-05-28 19:56:29 +02:00
|
|
|
if (isTrigger)
|
|
|
|
retval = PointerGetDatum(plpgsql_exec_trigger(func, trigdata));
|
|
|
|
else
|
|
|
|
retval = plpgsql_exec_function(func, fcinfo);
|
1998-09-01 06:40:42 +02:00
|
|
|
|
|
|
|
/* ----------
|
2000-05-28 19:56:29 +02:00
|
|
|
* Disconnect from SPI manager
|
1998-09-01 06:40:42 +02:00
|
|
|
* ----------
|
|
|
|
*/
|
2000-05-28 19:56:29 +02:00
|
|
|
if (SPI_finish() != SPI_OK_FINISH)
|
|
|
|
elog(ERROR, "plpgsql: SPI_finish() failed");
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2000-05-28 19:56:29 +02:00
|
|
|
return retval;
|
1998-08-22 14:38:39 +02:00
|
|
|
}
|