---------- * exec_eval_expr Evaluate an expression and return * the result Datum, along with data type/typmod. * * NOTE: caller must do exec_eval_cleanup when done with the Datum. * ---------- */
| 5612 | * ---------- |
| 5613 | */ |
| 5614 | static Datum |
| 5615 | exec_eval_expr(PLpgSQL_execstate *estate, |
| 5616 | PLpgSQL_expr *expr, |
| 5617 | bool *isNull, |
| 5618 | Oid *rettype, |
| 5619 | int32 *rettypmod) |
| 5620 | { |
| 5621 | Datum result = 0; |
| 5622 | int rc; |
| 5623 | Form_pg_attribute attr; |
| 5624 | |
| 5625 | /* |
| 5626 | * If first time through, create a plan for this expression. |
| 5627 | */ |
| 5628 | if (expr->plan == NULL) |
| 5629 | exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK); |
| 5630 | |
| 5631 | /* |
| 5632 | * If this is a simple expression, bypass SPI and use the executor |
| 5633 | * directly |
| 5634 | */ |
| 5635 | if (exec_eval_simple_expr(estate, expr, |
| 5636 | &result, isNull, rettype, rettypmod)) |
| 5637 | return result; |
| 5638 | |
| 5639 | /* |
| 5640 | * Else do it the hard way via exec_run_select |
| 5641 | */ |
| 5642 | rc = exec_run_select(estate, expr, 2, NULL); |
| 5643 | if (rc != SPI_OK_SELECT) |
| 5644 | ereport(ERROR, |
| 5645 | (errcode(ERRCODE_WRONG_OBJECT_TYPE), |
| 5646 | errmsg("query did not return data"), |
| 5647 | errcontext("query: %s", expr->query))); |
| 5648 | |
| 5649 | /* |
| 5650 | * Check that the expression returns exactly one column... |
| 5651 | */ |
| 5652 | if (estate->eval_tuptable->tupdesc->natts != 1) |
| 5653 | ereport(ERROR, |
| 5654 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 5655 | errmsg_plural("query returned %d column", |
| 5656 | "query returned %d columns", |
| 5657 | estate->eval_tuptable->tupdesc->natts, |
| 5658 | estate->eval_tuptable->tupdesc->natts), |
| 5659 | errcontext("query: %s", expr->query))); |
| 5660 | |
| 5661 | /* |
| 5662 | * ... and get the column's datatype. |
| 5663 | */ |
| 5664 | attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0); |
| 5665 | *rettype = attr->atttypid; |
| 5666 | *rettypmod = attr->atttypmod; |
| 5667 | |
| 5668 | /* |
| 5669 | * If there are no rows selected, the result is a NULL of that type. |
| 5670 | */ |
| 5671 | if (estate->eval_processed == 0) |
no test coverage detected