| 112 | } |
| 113 | |
| 114 | int |
| 115 | SPI_connect_ext(int options) |
| 116 | { |
| 117 | int newdepth; |
| 118 | |
| 119 | /* Enlarge stack if necessary */ |
| 120 | if (_SPI_stack == NULL) |
| 121 | { |
| 122 | if (_SPI_connected != -1 || _SPI_stack_depth != 0) |
| 123 | elog(ERROR, "SPI stack corrupted"); |
| 124 | newdepth = 16; |
| 125 | _SPI_stack = (_SPI_connection *) |
| 126 | MemoryContextAlloc(TopMemoryContext, |
| 127 | newdepth * sizeof(_SPI_connection)); |
| 128 | _SPI_stack_depth = newdepth; |
| 129 | } |
| 130 | else |
| 131 | { |
| 132 | if (_SPI_stack_depth <= 0 || _SPI_stack_depth <= _SPI_connected) |
| 133 | elog(ERROR, "SPI stack corrupted"); |
| 134 | if (_SPI_stack_depth == _SPI_connected + 1) |
| 135 | { |
| 136 | newdepth = _SPI_stack_depth * 2; |
| 137 | _SPI_stack = (_SPI_connection *) |
| 138 | repalloc(_SPI_stack, |
| 139 | newdepth * sizeof(_SPI_connection)); |
| 140 | _SPI_stack_depth = newdepth; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | /* Enter new stack level */ |
| 145 | _SPI_connected++; |
| 146 | Assert(_SPI_connected >= 0 && _SPI_connected < _SPI_stack_depth); |
| 147 | |
| 148 | _SPI_current = &(_SPI_stack[_SPI_connected]); |
| 149 | _SPI_current->processed = 0; |
| 150 | _SPI_current->tuptable = NULL; |
| 151 | _SPI_current->execSubid = InvalidSubTransactionId; |
| 152 | slist_init(&_SPI_current->tuptables); |
| 153 | _SPI_current->procCxt = NULL; /* in case we fail to create 'em */ |
| 154 | _SPI_current->execCxt = NULL; |
| 155 | _SPI_current->connectSubid = GetCurrentSubTransactionId(); |
| 156 | _SPI_current->queryEnv = NULL; |
| 157 | _SPI_current->atomic = (options & SPI_OPT_NONATOMIC ? false : true); |
| 158 | _SPI_current->internal_xact = false; |
| 159 | _SPI_current->outer_processed = SPI_processed; |
| 160 | _SPI_current->outer_tuptable = SPI_tuptable; |
| 161 | _SPI_current->outer_result = SPI_result; |
| 162 | |
| 163 | /* |
| 164 | * Create memory contexts for this procedure |
| 165 | * |
| 166 | * In atomic contexts (the normal case), we use TopTransactionContext, |
| 167 | * otherwise PortalContext, so that it lives across transaction |
| 168 | * boundaries. |
| 169 | * |
| 170 | * XXX It could be better to use PortalContext as the parent context in |
| 171 | * all cases, but we may not be inside a portal (consider deferred-trigger |
no test coverage detected