| 1 | /*------------------------------------------------------------------------- | 
|---|
| 2 | * | 
|---|
| 3 | * spi_priv.h | 
|---|
| 4 | *				Server Programming Interface private declarations | 
|---|
| 5 | * | 
|---|
| 6 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group | 
|---|
| 7 | * Portions Copyright (c) 1994, Regents of the University of California | 
|---|
| 8 | * | 
|---|
| 9 | * src/include/executor/spi_priv.h | 
|---|
| 10 | * | 
|---|
| 11 | *------------------------------------------------------------------------- | 
|---|
| 12 | */ | 
|---|
| 13 | #ifndef SPI_PRIV_H | 
|---|
| 14 | #define SPI_PRIV_H | 
|---|
| 15 |  | 
|---|
| 16 | #include "executor/spi.h" | 
|---|
| 17 | #include "utils/queryenvironment.h" | 
|---|
| 18 |  | 
|---|
| 19 |  | 
|---|
| 20 | #define _SPI_PLAN_MAGIC		569278163 | 
|---|
| 21 |  | 
|---|
| 22 | typedef struct | 
|---|
| 23 | { | 
|---|
| 24 | /* current results */ | 
|---|
| 25 | uint64		processed;		/* by Executor */ | 
|---|
| 26 | SPITupleTable *tuptable;	/* tuptable currently being built */ | 
|---|
| 27 |  | 
|---|
| 28 | /* subtransaction in which current Executor call was started */ | 
|---|
| 29 | SubTransactionId execSubid; | 
|---|
| 30 |  | 
|---|
| 31 | /* resources of this execution context */ | 
|---|
| 32 | slist_head	tuptables;		/* list of all live SPITupleTables */ | 
|---|
| 33 | MemoryContext procCxt;		/* procedure context */ | 
|---|
| 34 | MemoryContext execCxt;		/* executor context */ | 
|---|
| 35 | MemoryContext savedcxt;		/* context of SPI_connect's caller */ | 
|---|
| 36 | SubTransactionId connectSubid;	/* ID of connecting subtransaction */ | 
|---|
| 37 | QueryEnvironment *queryEnv; /* query environment setup for SPI level */ | 
|---|
| 38 |  | 
|---|
| 39 | /* transaction management support */ | 
|---|
| 40 | bool		atomic;			/* atomic execution context, does not allow | 
|---|
| 41 | * transactions */ | 
|---|
| 42 | bool		internal_xact;	/* SPI-managed transaction boundary, skip | 
|---|
| 43 | * cleanup */ | 
|---|
| 44 |  | 
|---|
| 45 | /* saved values of API global variables for previous nesting level */ | 
|---|
| 46 | uint64		outer_processed; | 
|---|
| 47 | SPITupleTable *outer_tuptable; | 
|---|
| 48 | int			outer_result; | 
|---|
| 49 | } _SPI_connection; | 
|---|
| 50 |  | 
|---|
| 51 | /* | 
|---|
| 52 | * SPI plans have three states: saved, unsaved, or temporary. | 
|---|
| 53 | * | 
|---|
| 54 | * Ordinarily, the _SPI_plan struct itself as well as the argtypes array | 
|---|
| 55 | * are in a dedicated memory context identified by plancxt (which can be | 
|---|
| 56 | * really small).  All the other subsidiary state is in plancache entries | 
|---|
| 57 | * identified by plancache_list (note: the list cells themselves are in | 
|---|
| 58 | * plancxt). | 
|---|
| 59 | * | 
|---|
| 60 | * In an unsaved plan, the plancxt as well as the plancache entries' contexts | 
|---|
| 61 | * are children of the SPI procedure context, so they'll all disappear at | 
|---|
| 62 | * function exit.  plancache.c also knows that the plancache entries are | 
|---|
| 63 | * "unsaved", so it doesn't link them into its global list; hence they do | 
|---|
| 64 | * not respond to inval events.  This is OK since we are presumably holding | 
|---|
| 65 | * adequate locks to prevent other backends from messing with the tables. | 
|---|
| 66 | * | 
|---|
| 67 | * For a saved plan, the plancxt is made a child of CacheMemoryContext | 
|---|
| 68 | * since it should persist until explicitly destroyed.  Likewise, the | 
|---|
| 69 | * plancache entries will be under CacheMemoryContext since we tell | 
|---|
| 70 | * plancache.c to save them.  We rely on plancache.c to keep the cache | 
|---|
| 71 | * entries up-to-date as needed in the face of invalidation events. | 
|---|
| 72 | * | 
|---|
| 73 | * There are also "temporary" SPI plans, in which the _SPI_plan struct is | 
|---|
| 74 | * not even palloc'd but just exists in some function's local variable. | 
|---|
| 75 | * The plancache entries are unsaved and exist under the SPI executor context, | 
|---|
| 76 | * while additional data such as argtypes and list cells is loose in the SPI | 
|---|
| 77 | * executor context.  Such plans can be identified by having plancxt == NULL. | 
|---|
| 78 | * | 
|---|
| 79 | * We can also have "one-shot" SPI plans (which are typically temporary, | 
|---|
| 80 | * as described above).  These are meant to be executed once and discarded, | 
|---|
| 81 | * and various optimizations are made on the assumption of single use. | 
|---|
| 82 | * Note in particular that the CachedPlanSources within such an SPI plan | 
|---|
| 83 | * are not "complete" until execution. | 
|---|
| 84 | * | 
|---|
| 85 | * Note: if the original query string contained only whitespace and comments, | 
|---|
| 86 | * the plancache_list will be NIL and so there is no place to store the | 
|---|
| 87 | * query string.  We don't care about that, but we do care about the | 
|---|
| 88 | * argument type array, which is why it's seemingly-redundantly stored. | 
|---|
| 89 | */ | 
|---|
| 90 | typedef struct _SPI_plan | 
|---|
| 91 | { | 
|---|
| 92 | int			magic;			/* should equal _SPI_PLAN_MAGIC */ | 
|---|
| 93 | bool		saved;			/* saved or unsaved plan? */ | 
|---|
| 94 | bool		oneshot;		/* one-shot plan? */ | 
|---|
| 95 | bool		no_snapshots;	/* let the caller handle the snapshots */ | 
|---|
| 96 | List	   *plancache_list; /* one CachedPlanSource per parsetree */ | 
|---|
| 97 | MemoryContext plancxt;		/* Context containing _SPI_plan and data */ | 
|---|
| 98 | int			cursor_options; /* Cursor options used for planning */ | 
|---|
| 99 | int			nargs;			/* number of plan arguments */ | 
|---|
| 100 | Oid		   *argtypes;		/* Argument types (NULL if nargs is 0) */ | 
|---|
| 101 | ParserSetupHook parserSetup;	/* alternative parameter spec method */ | 
|---|
| 102 | void	   *parserSetupArg; | 
|---|
| 103 | } _SPI_plan; | 
|---|
| 104 |  | 
|---|
| 105 | #endif							/* SPI_PRIV_H */ | 
|---|
| 106 |  | 
|---|