* check_sql_fn_retval() * Check return value of a list of lists of sql parse trees. * * The return value of a sql function is the value returned by the last * canSetTag query in the function. We do some ad-hoc type checking and * coercion here to ensure that the function returns what it's supposed to. * Note that we may actually modify the last query to make it match! * * This function r
| 1746 | * function is defined to return VOID then *resultTargetList is set to NIL. |
| 1747 | */ |
| 1748 | bool |
| 1749 | check_sql_fn_retval(List *queryTreeLists, |
| 1750 | Oid rettype, TupleDesc rettupdesc, |
| 1751 | bool insertDroppedCols, |
| 1752 | List **resultTargetList) |
| 1753 | { |
| 1754 | bool is_tuple_result = false; |
| 1755 | Query *parse; |
| 1756 | ListCell *parse_cell; |
| 1757 | List *tlist; |
| 1758 | int tlistlen; |
| 1759 | bool tlist_is_modifiable; |
| 1760 | char fn_typtype; |
| 1761 | List *upper_tlist = NIL; |
| 1762 | bool upper_tlist_nontrivial = false; |
| 1763 | ListCell *lc; |
| 1764 | |
| 1765 | if (resultTargetList) |
| 1766 | *resultTargetList = NIL; /* initialize in case of VOID result */ |
| 1767 | |
| 1768 | /* |
| 1769 | * If it's declared to return VOID, we don't care what's in the function. |
| 1770 | * (This takes care of the procedure case, as well.) |
| 1771 | */ |
| 1772 | if (rettype == VOIDOID) |
| 1773 | return false; |
| 1774 | |
| 1775 | /* |
| 1776 | * Find the last canSetTag query in the function body (which is presented |
| 1777 | * to us as a list of sublists of Query nodes). This isn't necessarily |
| 1778 | * the last parsetree, because rule rewriting can insert queries after |
| 1779 | * what the user wrote. Note that it might not even be in the last |
| 1780 | * sublist, for example if the last query rewrites to DO INSTEAD NOTHING. |
| 1781 | * (It might not be unreasonable to throw an error in such a case, but |
| 1782 | * this is the historical behavior and it doesn't seem worth changing.) |
| 1783 | */ |
| 1784 | parse = NULL; |
| 1785 | parse_cell = NULL; |
| 1786 | foreach(lc, queryTreeLists) |
| 1787 | { |
| 1788 | List *sublist = lfirst_node(List, lc); |
| 1789 | ListCell *lc2; |
| 1790 | |
| 1791 | foreach(lc2, sublist) |
| 1792 | { |
| 1793 | Query *q = lfirst_node(Query, lc2); |
| 1794 | |
| 1795 | if (q->canSetTag) |
| 1796 | { |
| 1797 | parse = q; |
| 1798 | parse_cell = lc2; |
| 1799 | } |
| 1800 | } |
| 1801 | } |
| 1802 | |
| 1803 | /* |
| 1804 | * If it's a plain SELECT, it returns whatever the targetlist says. |
| 1805 | * Otherwise, if it's INSERT/UPDATE/DELETE with RETURNING, it returns |
no test coverage detected