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