mirror of
https://github.com/postgres/postgres.git
synced 2026-02-17 01:31:07 -05:00
A QueryEnvironment concept is added, which allows new types of objects to be passed into queries from parsing on through execution. At this point, the only thing implemented is a collection of EphemeralNamedRelation objects -- relations which can be referenced by name in queries, but do not exist in the catalogs. The only type of ENR implemented is NamedTuplestore, but provision is made to add more types fairly easily. An ENR can carry its own TupleDesc or reference a relation in the catalogs by relid. Although these features can be used without SPI, convenience functions are added to SPI so that ENRs can easily be used by code run through SPI. The initial use of all this is going to be transition tables in AFTER triggers, but that will be added to each PL as a separate commit. An incidental effect of this patch is to produce a more informative error message if an attempt is made to modify the contents of a CTE from a referencing DML statement. No tests previously covered that possibility, so one is added. Kevin Grittner and Thomas Munro Reviewed by Heikki Linnakangas, David Fetter, and Thomas Munro with valuable comments and suggestions from many others
91 lines
3.9 KiB
C
91 lines
3.9 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* spi_priv.h
|
|
* Server Programming Interface private declarations
|
|
*
|
|
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/executor/spi_priv.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef SPI_PRIV_H
|
|
#define SPI_PRIV_H
|
|
|
|
#include "executor/spi.h"
|
|
#include "utils/queryenvironment.h"
|
|
|
|
|
|
#define _SPI_PLAN_MAGIC 569278163
|
|
|
|
typedef struct
|
|
{
|
|
/* current results */
|
|
uint64 processed; /* by Executor */
|
|
Oid lastoid;
|
|
SPITupleTable *tuptable; /* tuptable currently being built */
|
|
|
|
/* resources of this execution context */
|
|
slist_head tuptables; /* list of all live SPITupleTables */
|
|
MemoryContext procCxt; /* procedure context */
|
|
MemoryContext execCxt; /* executor context */
|
|
MemoryContext savedcxt; /* context of SPI_connect's caller */
|
|
SubTransactionId connectSubid; /* ID of connecting subtransaction */
|
|
QueryEnvironment *queryEnv; /* query environment setup for SPI level */
|
|
} _SPI_connection;
|
|
|
|
/*
|
|
* SPI plans have three states: saved, unsaved, or temporary.
|
|
*
|
|
* Ordinarily, the _SPI_plan struct itself as well as the argtypes array
|
|
* are in a dedicated memory context identified by plancxt (which can be
|
|
* really small). All the other subsidiary state is in plancache entries
|
|
* identified by plancache_list (note: the list cells themselves are in
|
|
* plancxt).
|
|
*
|
|
* In an unsaved plan, the plancxt as well as the plancache entries' contexts
|
|
* are children of the SPI procedure context, so they'll all disappear at
|
|
* function exit. plancache.c also knows that the plancache entries are
|
|
* "unsaved", so it doesn't link them into its global list; hence they do
|
|
* not respond to inval events. This is OK since we are presumably holding
|
|
* adequate locks to prevent other backends from messing with the tables.
|
|
*
|
|
* For a saved plan, the plancxt is made a child of CacheMemoryContext
|
|
* since it should persist until explicitly destroyed. Likewise, the
|
|
* plancache entries will be under CacheMemoryContext since we tell
|
|
* plancache.c to save them. We rely on plancache.c to keep the cache
|
|
* entries up-to-date as needed in the face of invalidation events.
|
|
*
|
|
* There are also "temporary" SPI plans, in which the _SPI_plan struct is
|
|
* not even palloc'd but just exists in some function's local variable.
|
|
* The plancache entries are unsaved and exist under the SPI executor context,
|
|
* while additional data such as argtypes and list cells is loose in the SPI
|
|
* executor context. Such plans can be identified by having plancxt == NULL.
|
|
*
|
|
* We can also have "one-shot" SPI plans (which are typically temporary,
|
|
* as described above). These are meant to be executed once and discarded,
|
|
* and various optimizations are made on the assumption of single use.
|
|
* Note in particular that the CachedPlanSources within such an SPI plan
|
|
* are not "complete" until execution.
|
|
*
|
|
* Note: if the original query string contained only whitespace and comments,
|
|
* the plancache_list will be NIL and so there is no place to store the
|
|
* query string. We don't care about that, but we do care about the
|
|
* argument type array, which is why it's seemingly-redundantly stored.
|
|
*/
|
|
typedef struct _SPI_plan
|
|
{
|
|
int magic; /* should equal _SPI_PLAN_MAGIC */
|
|
bool saved; /* saved or unsaved plan? */
|
|
bool oneshot; /* one-shot plan? */
|
|
List *plancache_list; /* one CachedPlanSource per parsetree */
|
|
MemoryContext plancxt; /* Context containing _SPI_plan and data */
|
|
int cursor_options; /* Cursor options used for planning */
|
|
int nargs; /* number of plan arguments */
|
|
Oid *argtypes; /* Argument types (NULL if nargs is 0) */
|
|
ParserSetupHook parserSetup; /* alternative parameter spec method */
|
|
void *parserSetupArg;
|
|
} _SPI_plan;
|
|
|
|
#endif /* SPI_PRIV_H */
|