summaryrefslogtreecommitdiff
path: root/src/pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/pl')
-rw-r--r--src/pl/plperl/plperl.c25
-rw-r--r--src/pl/plpgsql/src/pl_exec.c20
-rw-r--r--src/pl/plpgsql/src/plpgsql.h2
-rw-r--r--src/pl/plpython/plpy_cursorobject.c18
-rw-r--r--src/pl/plpython/plpy_spi.c28
-rw-r--r--src/pl/tcl/pltcl.c19
6 files changed, 79 insertions, 33 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index cd917ab8e46..269f7f33220 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -12,8 +12,9 @@
/* system stuff */
#include <ctype.h>
#include <fcntl.h>
-#include <unistd.h>
+#include <limits.h>
#include <locale.h>
+#include <unistd.h>
/* postgreSQL stuff */
#include "access/htup_details.h"
@@ -281,7 +282,7 @@ static Datum plperl_hash_to_datum(SV *src, TupleDesc td);
static void plperl_init_shared_libs(pTHX);
static void plperl_trusted_init(void);
static void plperl_untrusted_init(void);
-static HV *plperl_spi_execute_fetch_result(SPITupleTable *, int, int);
+static HV *plperl_spi_execute_fetch_result(SPITupleTable *, uint64, int);
static char *hek2cstr(HE *he);
static SV **hv_store_string(HV *hv, const char *key, SV *val);
static SV **hv_fetch_string(HV *hv, const char *key);
@@ -1472,7 +1473,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
hv = newHV();
(void) hv_store(hv, "array", 5, av, 0);
- (void) hv_store(hv, "typeoid", 7, newSViv(typid), 0);
+ (void) hv_store(hv, "typeoid", 7, newSVuv(typid), 0);
return sv_bless(newRV_noinc((SV *) hv),
gv_stashpv("PostgreSQL::InServer::ARRAY", 0));
@@ -3091,7 +3092,7 @@ plperl_spi_exec(char *query, int limit)
static HV *
-plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
+plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed,
int status)
{
HV *result;
@@ -3103,13 +3104,25 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
hv_store_string(result, "status",
cstr2sv(SPI_result_code_string(status)));
hv_store_string(result, "processed",
- newSViv(processed));
+ (processed > (uint64) INT_MAX) ?
+ newSVnv((double) processed) :
+ newSViv((int) processed));
if (status > 0 && tuptable)
{
AV *rows;
SV *row;
- int i;
+ uint64 i;
+
+ /*
+ * av_extend's 2nd argument is declared I32. It's possible we could
+ * nonetheless push more than INT_MAX elements into a Perl array, but
+ * let's just fail instead of trying.
+ */
+ if (processed > (uint64) INT_MAX)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("query result has too many rows to fit in a Perl array")));
rows = newAV();
av_extend(rows, processed);
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index bd58d5f444f..b63ecacdecf 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -1601,8 +1601,8 @@ exec_stmt_getdiag(PLpgSQL_execstate *estate, PLpgSQL_stmt_getdiag *stmt)
{
case PLPGSQL_GETDIAG_ROW_COUNT:
exec_assign_value(estate, var,
- UInt32GetDatum(estate->eval_processed),
- false, INT4OID, -1);
+ UInt64GetDatum(estate->eval_processed),
+ false, INT8OID, -1);
break;
case PLPGSQL_GETDIAG_RESULT_OID:
@@ -2856,7 +2856,7 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
PLpgSQL_stmt_return_query *stmt)
{
Portal portal;
- uint32 processed = 0;
+ uint64 processed = 0;
TupleConversionMap *tupmap;
if (!estate->retisset)
@@ -2887,7 +2887,7 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
while (true)
{
- int i;
+ uint64 i;
SPI_cursor_fetch(portal, true, 50);
if (SPI_processed == 0)
@@ -3579,7 +3579,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
if (stmt->into)
{
SPITupleTable *tuptab = SPI_tuptable;
- uint32 n = SPI_processed;
+ uint64 n = SPI_processed;
PLpgSQL_rec *rec = NULL;
PLpgSQL_row *row = NULL;
@@ -3769,7 +3769,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
if (stmt->into)
{
SPITupleTable *tuptab = SPI_tuptable;
- uint32 n = SPI_processed;
+ uint64 n = SPI_processed;
PLpgSQL_rec *rec = NULL;
PLpgSQL_row *row = NULL;
@@ -4043,7 +4043,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
SPITupleTable *tuptab;
Portal portal;
char *curname;
- uint32 n;
+ uint64 n;
/* ----------
* Get the portal of the cursor by name
@@ -5151,7 +5151,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
SPITupleTable *tuptab;
bool found = false;
int rc = PLPGSQL_RC_OK;
- int n;
+ uint64 n;
/*
* Determine if we assign to a record or a row
@@ -5182,7 +5182,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
* If the query didn't return any rows, set the target to NULL and fall
* through with found = false.
*/
- if (n <= 0)
+ if (n == 0)
{
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
exec_eval_cleanup(estate);
@@ -5195,7 +5195,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
*/
while (n > 0)
{
- int i;
+ uint64 i;
for (i = 0; i < n; i++)
{
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index a1e900d7336..2deece43eb7 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -820,7 +820,7 @@ typedef struct PLpgSQL_execstate
/* 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 */
diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c
index 103571ba15c..44ba76e765e 100644
--- a/src/pl/plpython/plpy_cursorobject.c
+++ b/src/pl/plpython/plpy_cursorobject.c
@@ -6,6 +6,8 @@
#include "postgres.h"
+#include <limits.h>
+
#include "access/xact.h"
#include "mb/pg_wchar.h"
#include "utils/memutils.h"
@@ -446,11 +448,23 @@ PLy_cursor_fetch(PyObject *self, PyObject *args)
ret->status = PyInt_FromLong(SPI_OK_FETCH);
Py_DECREF(ret->nrows);
- ret->nrows = PyInt_FromLong(SPI_processed);
+ ret->nrows = (SPI_processed > (uint64) LONG_MAX) ?
+ PyFloat_FromDouble((double) SPI_processed) :
+ PyInt_FromLong((long) SPI_processed);
if (SPI_processed != 0)
{
- int i;
+ uint64 i;
+
+ /*
+ * PyList_New() and PyList_SetItem() use Py_ssize_t for list size
+ * and list indices; so we cannot support a result larger than
+ * PY_SSIZE_T_MAX.
+ */
+ if (SPI_processed > (uint64) PY_SSIZE_T_MAX)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("query result has too many rows to fit in a Python list")));
Py_DECREF(ret->rows);
ret->rows = PyList_New(SPI_processed);
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
index 58e78ecebcb..7d84629f48f 100644
--- a/src/pl/plpython/plpy_spi.c
+++ b/src/pl/plpython/plpy_spi.c
@@ -6,6 +6,8 @@
#include "postgres.h"
+#include <limits.h>
+
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
@@ -29,7 +31,8 @@
static PyObject *PLy_spi_execute_query(char *query, long limit);
static PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit);
-static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status);
+static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable,
+ uint64 rows, int status);
static void PLy_spi_exception_set(PyObject *excclass, ErrorData *edata);
@@ -382,7 +385,7 @@ PLy_spi_execute_query(char *query, long limit)
}
static PyObject *
-PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
+PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status)
{
PLyResultObject *result;
volatile MemoryContext oldcontext;
@@ -394,16 +397,19 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
if (status > 0 && tuptable == NULL)
{
Py_DECREF(result->nrows);
- result->nrows = PyInt_FromLong(rows);
+ result->nrows = (rows > (uint64) LONG_MAX) ?
+ PyFloat_FromDouble((double) rows) :
+ PyInt_FromLong((long) rows);
}
else if (status > 0 && tuptable != NULL)
{
PLyTypeInfo args;
- int i;
MemoryContext cxt;
Py_DECREF(result->nrows);
- result->nrows = PyInt_FromLong(rows);
+ result->nrows = (rows > (uint64) LONG_MAX) ?
+ PyFloat_FromDouble((double) rows) :
+ PyInt_FromLong((long) rows);
cxt = AllocSetContextCreate(CurrentMemoryContext,
"PL/Python temp context",
@@ -419,6 +425,18 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
if (rows)
{
+ uint64 i;
+
+ /*
+ * PyList_New() and PyList_SetItem() use Py_ssize_t for list
+ * size and list indices; so we cannot support a result larger
+ * than PY_SSIZE_T_MAX.
+ */
+ if (rows > (uint64) PY_SSIZE_T_MAX)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("query result has too many rows to fit in a Python list")));
+
Py_DECREF(result->rows);
result->rows = PyList_New(rows);
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 105b6186f64..5b27c731b6e 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -226,7 +226,7 @@ static int pltcl_process_SPI_result(Tcl_Interp *interp,
Tcl_Obj *loop_body,
int spi_rc,
SPITupleTable *tuptable,
- int ntuples);
+ uint64 ntuples);
static int pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
static int pltcl_SPI_execute_plan(ClientData cdata, Tcl_Interp *interp,
@@ -235,7 +235,7 @@ static int pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
static void pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname,
- int tupno, HeapTuple tuple, TupleDesc tupdesc);
+ uint64 tupno, HeapTuple tuple, TupleDesc tupdesc);
static Tcl_Obj *pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc);
@@ -481,7 +481,7 @@ pltcl_init_load_unknown(Tcl_Interp *interp)
int tcl_rc;
Tcl_DString unknown_src;
char *part;
- int i;
+ uint64 i;
int fno;
/************************************************************
@@ -2007,10 +2007,9 @@ pltcl_process_SPI_result(Tcl_Interp *interp,
Tcl_Obj *loop_body,
int spi_rc,
SPITupleTable *tuptable,
- int ntuples)
+ uint64 ntuples)
{
int my_rc = TCL_OK;
- int i;
int loop_rc;
HeapTuple *tuples;
TupleDesc tupdesc;
@@ -2021,7 +2020,7 @@ pltcl_process_SPI_result(Tcl_Interp *interp,
case SPI_OK_INSERT:
case SPI_OK_DELETE:
case SPI_OK_UPDATE:
- Tcl_SetObjResult(interp, Tcl_NewIntObj(ntuples));
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(ntuples));
break;
case SPI_OK_UTILITY:
@@ -2060,6 +2059,8 @@ pltcl_process_SPI_result(Tcl_Interp *interp,
* There is a loop body - process all tuples and evaluate the
* body on each
*/
+ uint64 i;
+
for (i = 0; i < ntuples; i++)
{
pltcl_set_tuple_values(interp, arrayname, i,
@@ -2085,7 +2086,7 @@ pltcl_process_SPI_result(Tcl_Interp *interp,
if (my_rc == TCL_OK)
{
- Tcl_SetObjResult(interp, Tcl_NewIntObj(ntuples));
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(ntuples));
}
break;
@@ -2472,7 +2473,7 @@ pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp,
**********************************************************************/
static void
pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname,
- int tupno, HeapTuple tuple, TupleDesc tupdesc)
+ uint64 tupno, HeapTuple tuple, TupleDesc tupdesc)
{
int i;
char *outputstr;
@@ -2498,7 +2499,7 @@ pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname,
{
arrptr = &arrayname;
nameptr = &attname;
- Tcl_SetVar2Ex(interp, arrayname, ".tupno", Tcl_NewIntObj(tupno), 0);
+ Tcl_SetVar2Ex(interp, arrayname, ".tupno", Tcl_NewWideIntObj(tupno), 0);
}
for (i = 0; i < tupdesc->natts; i++)