diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index 7162fdb7aa343ccb4490715ea4f4065f8148b43b..3fe6be9bd1d3cf2f3a899d3617c84d682dcdacd6 100644 --- a/doc/src/sgml/spi.sgml +++ b/doc/src/sgml/spi.sgml @@ -377,7 +377,10 @@ SPI_execute("INSERT INTO foo SELECT * FROM bar", false, 5); global pointer <literal>SPITupleTable *SPI_tuptable</literal> to access the result rows. Some utility commands (such as <command>EXPLAIN</>) also return row sets, and <literal>SPI_tuptable</> - will contain the result in these cases too. + will contain the result in these cases too. Some utility commands + (<command>COPY</>, <command>CREATE TABLE AS</>) don't return a row set, so + <literal>SPI_tuptable</> is NULL, but they still return the number of + rows processed in <varname>SPI_processed</>. </para> <para> diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 70d600490507f6797a5d4079f5cb51ad19d28018..bf8c4c711369a4637d936e1e2b7d88b22083891c 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -1922,25 +1922,31 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, _SPI_current->processed = _SPI_current->tuptable->alloced - _SPI_current->tuptable->free; + res = SPI_OK_UTILITY; + /* - * CREATE TABLE AS is a messy special case for historical - * reasons. We must set _SPI_current->processed even though - * the tuples weren't returned to the caller, and we must - * return a special result code if the statement was spelled - * SELECT INTO. + * Some utility statements return a row count, even though the + * tuples are not returned to the caller. */ if (IsA(stmt, CreateTableAsStmt)) { Assert(strncmp(completionTag, "SELECT ", 7) == 0); _SPI_current->processed = strtoul(completionTag + 7, NULL, 10); + + /* + * For historical reasons, if CREATE TABLE AS was spelled + * as SELECT INTO, return a special return code. + */ if (((CreateTableAsStmt *) stmt)->is_select_into) res = SPI_OK_SELINTO; - else - res = SPI_OK_UTILITY; } - else - res = SPI_OK_UTILITY; + else if (IsA(stmt, CopyStmt)) + { + Assert(strncmp(completionTag, "COPY ", 5) == 0); + _SPI_current->processed = strtoul(completionTag + 5, + NULL, 10); + } } /*