---------- * Generate a prepared plan * * CAUTION: it is possible for this function to throw an error after it has * built a SPIPlan and saved it in expr->plan. Therefore, be wary of doing * additional things contingent on expr->plan being NULL. That is, given * code like * * if (query->plan == NULL) * { * // okay to put setup code here * exec_prepare_plan(estate, query, ...); * /
| 4111 | * ---------- |
| 4112 | */ |
| 4113 | static void |
| 4114 | exec_prepare_plan(PLpgSQL_execstate *estate, |
| 4115 | PLpgSQL_expr *expr, int cursorOptions) |
| 4116 | { |
| 4117 | SPIPlanPtr plan; |
| 4118 | SPIPrepareOptions options; |
| 4119 | |
| 4120 | /* |
| 4121 | * The grammar can't conveniently set expr->func while building the parse |
| 4122 | * tree, so make sure it's set before parser hooks need it. |
| 4123 | */ |
| 4124 | expr->func = estate->func; |
| 4125 | |
| 4126 | /* |
| 4127 | * Generate and save the plan |
| 4128 | */ |
| 4129 | memset(&options, 0, sizeof(options)); |
| 4130 | options.parserSetup = (ParserSetupHook) plpgsql_parser_setup; |
| 4131 | options.parserSetupArg = (void *) expr; |
| 4132 | options.parseMode = expr->parseMode; |
| 4133 | options.cursorOptions = cursorOptions; |
| 4134 | plan = SPI_prepare_extended(expr->query, &options); |
| 4135 | if (plan == NULL) |
| 4136 | elog(ERROR, "SPI_prepare_extended failed for \"%s\": %s", |
| 4137 | expr->query, SPI_result_code_string(SPI_result)); |
| 4138 | |
| 4139 | SPI_keepplan(plan); |
| 4140 | expr->plan = plan; |
| 4141 | |
| 4142 | /* Check to see if it's a simple expression */ |
| 4143 | exec_simple_check_plan(estate, expr); |
| 4144 | } |
| 4145 | |
| 4146 | |
| 4147 | /* ---------- |
no test coverage detected