Hello,
one of our customers approached us and complained, that GET DIAGNOSTICS row_count returns invalid results if the number of rows is > 2^31. It's a bit complicated to test for this case, so I set up a separate instance with this patch, and inserted 2^32+x rows into a table. Internally, row_count it's a signed integer, the resulting number is negative:
diagnostics=# select testfunc_pg((2^31 + 50000)::bigint); testfunc_pg ------------- -2147433648 (1 row) Going over 2^32 wraps around: diagnostics=# select testfunc_pg((2^32 + 50000)::bigint); testfunc_pg ------------- 50000 (1 row) Attached patch expands the row_count to 64 bit. diagnostics=# select testfunc_pg((2^32 + 50000)::bigint); testfunc_pg ------------- 4295017296 (1 row) I hope, I covered all the places which count the result set. Regards, -- Andreas 'ads' Scherbaum German PostgreSQL User Group European PostgreSQL User Group - Board of Directors Volunteer Regional Contact, Germany - PostgreSQL Project
diff -ru postgresql-9.5.0.orig/src/backend/executor/spi.c postgresql-9.5.0/src/backend/executor/spi.c --- postgresql-9.5.0.orig/src/backend/executor/spi.c 2016-01-04 22:29:34.000000000 +0100 +++ postgresql-9.5.0/src/backend/executor/spi.c 2016-01-27 01:30:06.099132294 +0100 @@ -36,7 +36,7 @@ #include "utils/typcache.h" -uint32 SPI_processed = 0; +uint64 SPI_processed = 0; Oid SPI_lastoid = InvalidOid; SPITupleTable *SPI_tuptable = NULL; int SPI_result; @@ -1994,7 +1994,7 @@ bool read_only, bool fire_triggers, long tcount) { int my_res = 0; - uint32 my_processed = 0; + uint64 my_processed = 0; Oid my_lastoid = InvalidOid; SPITupleTable *my_tuptable = NULL; int res = 0; @@ -2562,7 +2562,7 @@ static bool _SPI_checktuples(void) { - uint32 processed = _SPI_current->processed; + uint64 processed = _SPI_current->processed; SPITupleTable *tuptable = _SPI_current->tuptable; bool failed = false; diff -ru postgresql-9.5.0.orig/src/backend/tcop/pquery.c postgresql-9.5.0/src/backend/tcop/pquery.c --- postgresql-9.5.0.orig/src/backend/tcop/pquery.c 2016-01-04 22:29:34.000000000 +0100 +++ postgresql-9.5.0/src/backend/tcop/pquery.c 2016-01-30 12:11:56.573841810 +0100 @@ -195,7 +195,7 @@ { case CMD_SELECT: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "SELECT %u", queryDesc->estate->es_processed); + "SELECT %lu", queryDesc->estate->es_processed); break; case CMD_INSERT: if (queryDesc->estate->es_processed == 1) @@ -203,15 +203,15 @@ else lastOid = InvalidOid; snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "INSERT %u %u", lastOid, queryDesc->estate->es_processed); + "INSERT %u %lu", lastOid, queryDesc->estate->es_processed); break; case CMD_UPDATE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "UPDATE %u", queryDesc->estate->es_processed); + "UPDATE %lu", queryDesc->estate->es_processed); break; case CMD_DELETE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "DELETE %u", queryDesc->estate->es_processed); + "DELETE %lu", queryDesc->estate->es_processed); break; default: strcpy(completionTag, "???"); @@ -892,7 +892,7 @@ { QueryDesc *queryDesc; ScanDirection direction; - uint32 nprocessed; + uint64 nprocessed; /* * NB: queryDesc will be NULL if we are fetching from a held cursor or a diff -ru postgresql-9.5.0.orig/src/include/executor/spi.h postgresql-9.5.0/src/include/executor/spi.h --- postgresql-9.5.0.orig/src/include/executor/spi.h 2016-01-04 22:29:34.000000000 +0100 +++ postgresql-9.5.0/src/include/executor/spi.h 2016-01-27 01:34:46.388245129 +0100 @@ -59,7 +59,7 @@ #define SPI_OK_UPDATE_RETURNING 13 #define SPI_OK_REWRITTEN 14 -extern PGDLLIMPORT uint32 SPI_processed; +extern PGDLLIMPORT uint64 SPI_processed; extern PGDLLIMPORT Oid SPI_lastoid; extern PGDLLIMPORT SPITupleTable *SPI_tuptable; extern PGDLLIMPORT int SPI_result; diff -ru postgresql-9.5.0.orig/src/include/executor/spi_priv.h postgresql-9.5.0/src/include/executor/spi_priv.h --- postgresql-9.5.0.orig/src/include/executor/spi_priv.h 2016-01-04 22:29:34.000000000 +0100 +++ postgresql-9.5.0/src/include/executor/spi_priv.h 2016-01-27 01:34:55.220056918 +0100 @@ -21,7 +21,7 @@ typedef struct { /* current results */ - uint32 processed; /* by Executor */ + uint64 processed; /* by Executor */ Oid lastoid; SPITupleTable *tuptable; /* tuptable currently being built */ diff -ru postgresql-9.5.0.orig/src/include/nodes/execnodes.h postgresql-9.5.0/src/include/nodes/execnodes.h --- postgresql-9.5.0.orig/src/include/nodes/execnodes.h 2016-01-04 22:29:34.000000000 +0100 +++ postgresql-9.5.0/src/include/nodes/execnodes.h 2016-01-27 01:32:04.711625720 +0100 @@ -387,7 +387,7 @@ List *es_rowMarks; /* List of ExecRowMarks */ - uint32 es_processed; /* # of tuples processed */ + uint64 es_processed; /* # of tuples processed */ Oid es_lastoid; /* last oid processed (by INSERT) */ int es_top_eflags; /* eflags passed to ExecutorStart */ diff -ru postgresql-9.5.0.orig/src/pl/plpgsql/src/pl_exec.c postgresql-9.5.0/src/pl/plpgsql/src/pl_exec.c --- postgresql-9.5.0.orig/src/pl/plpgsql/src/pl_exec.c 2016-01-04 22:29:34.000000000 +0100 +++ postgresql-9.5.0/src/pl/plpgsql/src/pl_exec.c 2016-01-31 14:24:41.691784134 +0100 @@ -1642,8 +1642,10 @@ { case PLPGSQL_GETDIAG_ROW_COUNT: exec_assign_value(estate, var, - UInt32GetDatum(estate->eval_processed), - false, INT4OID, -1); + /* Int64GetDatum() instead of UInt64GetDatum(), + because there is no UInt64GetDatum() */ + Int64GetDatum(estate->eval_processed), + false, INT8OID, -1); break; case PLPGSQL_GETDIAG_RESULT_OID: @@ -2906,7 +2908,7 @@ PLpgSQL_stmt_return_query *stmt) { Portal portal; - uint32 processed = 0; + uint64 processed = 0; TupleConversionMap *tupmap; if (!estate->retisset) @@ -3630,7 +3632,7 @@ if (stmt->into) { SPITupleTable *tuptab = SPI_tuptable; - uint32 n = SPI_processed; + uint64 n = SPI_processed; PLpgSQL_rec *rec = NULL; PLpgSQL_row *row = NULL; @@ -3820,7 +3822,7 @@ if (stmt->into) { SPITupleTable *tuptab = SPI_tuptable; - uint32 n = SPI_processed; + uint64 n = SPI_processed; PLpgSQL_rec *rec = NULL; PLpgSQL_row *row = NULL; @@ -4092,7 +4094,7 @@ SPITupleTable *tuptab; Portal portal; char *curname; - uint32 n; + uint64 n; /* ---------- * Get the portal of the cursor by name @@ -5192,8 +5194,8 @@ PLpgSQL_row *row = NULL; SPITupleTable *tuptab; bool found = false; - int rc = PLPGSQL_RC_OK; - int n; + int rc = PLPGSQL_RC_OK; + int64 n; /* * Determine if we assign to a record or a row diff -ru postgresql-9.5.0.orig/src/pl/plpgsql/src/plpgsql.h postgresql-9.5.0/src/pl/plpgsql/src/plpgsql.h --- postgresql-9.5.0.orig/src/pl/plpgsql/src/plpgsql.h 2016-01-04 22:29:34.000000000 +0100 +++ postgresql-9.5.0/src/pl/plpgsql/src/plpgsql.h 2016-01-27 00:30:27.612711562 +0100 @@ -802,7 +802,7 @@ /* temporary state for results from evaluation of query or expr */ SPITupleTable *eval_tuptable; - uint32 eval_processed; + uint64 eval_processed; Oid eval_lastoid; ExprContext *eval_econtext; /* for executing simple expressions */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers