| 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 | |