* Returns true if the plan contains exactly one command * and that command returns tuples to the caller (eg, SELECT or * INSERT ... RETURNING, but not SELECT ... INTO). In essence, * the result indicates if the command can be used with SPI_cursor_open * * Parameters * plan: A plan previously prepared using SPI_prepare */
| 1960 | * plan: A plan previously prepared using SPI_prepare |
| 1961 | */ |
| 1962 | bool |
| 1963 | SPI_is_cursor_plan(SPIPlanPtr plan) |
| 1964 | { |
| 1965 | CachedPlanSource *plansource; |
| 1966 | |
| 1967 | if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC) |
| 1968 | { |
| 1969 | SPI_result = SPI_ERROR_ARGUMENT; |
| 1970 | return false; |
| 1971 | } |
| 1972 | |
| 1973 | if (list_length(plan->plancache_list) != 1) |
| 1974 | { |
| 1975 | SPI_result = 0; |
| 1976 | return false; /* not exactly 1 pre-rewrite command */ |
| 1977 | } |
| 1978 | plansource = (CachedPlanSource *) linitial(plan->plancache_list); |
| 1979 | |
| 1980 | /* |
| 1981 | * We used to force revalidation of the cached plan here, but that seems |
| 1982 | * unnecessary: invalidation could mean a change in the rowtype of the |
| 1983 | * tuples returned by a plan, but not whether it returns tuples at all. |
| 1984 | */ |
| 1985 | SPI_result = 0; |
| 1986 | |
| 1987 | /* Does it return tuples? */ |
| 1988 | if (plansource->resultDesc) |
| 1989 | return true; |
| 1990 | |
| 1991 | return false; |
| 1992 | } |
| 1993 | |
| 1994 | /* |
| 1995 | * SPI_plan_is_valid --- test whether a SPI plan is currently valid |
no test coverage detected