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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers