* Open portal for dynamic query * * Caution: this resets the stmt_mcontext at exit. We might eventually need * to move that responsibility to the callers, but currently no caller needs * to have statement-lifetime temp data that survives past this, so it's * simpler to do it here. */
| 8576 | * simpler to do it here. |
| 8577 | */ |
| 8578 | static Portal |
| 8579 | exec_dynquery_with_params(PLpgSQL_execstate *estate, |
| 8580 | PLpgSQL_expr *dynquery, |
| 8581 | List *params, |
| 8582 | const char *portalname, |
| 8583 | int cursorOptions) |
| 8584 | { |
| 8585 | Portal portal; |
| 8586 | Datum query; |
| 8587 | bool isnull; |
| 8588 | Oid restype; |
| 8589 | int32 restypmod; |
| 8590 | char *querystr; |
| 8591 | SPIParseOpenOptions options; |
| 8592 | MemoryContext stmt_mcontext = get_stmt_mcontext(estate); |
| 8593 | |
| 8594 | /* |
| 8595 | * Evaluate the string expression after the EXECUTE keyword. Its result is |
| 8596 | * the querystring we have to execute. |
| 8597 | */ |
| 8598 | query = exec_eval_expr(estate, dynquery, &isnull, &restype, &restypmod); |
| 8599 | if (isnull) |
| 8600 | ereport(ERROR, |
| 8601 | (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), |
| 8602 | errmsg("query string argument of EXECUTE is null"))); |
| 8603 | |
| 8604 | /* Get the C-String representation */ |
| 8605 | querystr = convert_value_to_string(estate, query, restype); |
| 8606 | |
| 8607 | /* copy it into the stmt_mcontext before we clean up */ |
| 8608 | querystr = MemoryContextStrdup(stmt_mcontext, querystr); |
| 8609 | |
| 8610 | exec_eval_cleanup(estate); |
| 8611 | |
| 8612 | /* |
| 8613 | * Open an implicit cursor for the query. We use SPI_cursor_parse_open |
| 8614 | * even when there are no params, because this avoids making and freeing |
| 8615 | * one copy of the plan. |
| 8616 | */ |
| 8617 | memset(&options, 0, sizeof(options)); |
| 8618 | options.params = exec_eval_using_params(estate, params); |
| 8619 | options.cursorOptions = cursorOptions; |
| 8620 | options.read_only = estate->readonly_func; |
| 8621 | |
| 8622 | portal = SPI_cursor_parse_open(portalname, querystr, &options); |
| 8623 | |
| 8624 | if (portal == NULL) |
| 8625 | elog(ERROR, "could not open implicit cursor for query \"%s\": %s", |
| 8626 | querystr, SPI_result_code_string(SPI_result)); |
| 8627 | |
| 8628 | /* Release transient data */ |
| 8629 | MemoryContextReset(stmt_mcontext); |
| 8630 | |
| 8631 | return portal; |
| 8632 | } |
| 8633 | |
| 8634 | /* |
| 8635 | * Return a formatted string with information about an expression's parameters, |
no test coverage detected