[PATCH] Use correct types and limits for PL/Perl SPI query results - Mailing list pgsql-hackers
| From | ilmari@ilmari.org (Dagfinn Ilmari Mannsåker) |
|---|---|
| Subject | [PATCH] Use correct types and limits for PL/Perl SPI query results |
| Date | |
| Msg-id | d8jmvq19kic.fsf@dalvik.ping.uio.no Whole thread Raw |
| Responses |
Re: [PATCH] Use correct types and limits for PL/Perl SPI query results
|
| List | pgsql-hackers |
Hi hackers,
Commit 23a27b039d94ba359286694831eafe03cd970eef changed the type of
numbers-of-tuples-processed counters to uint64 and adjusted various PLs
to cope with this. I noticed the PL/Perl changes did not take full
advantage of what Perl is capable of handling, so here's a patch that
improves that.
1) Perl's integers are at least pointer-sized and either signed or
unsigned, so can potentially hold up to 2⁶⁴-1. Floating point numbers
can also be larger than double (up to 128bit), allowing for exact
representation of integers beyond 2⁵³. Hence, adjust the setting of
the "processed" hash item to use UV_MAX for the limit and (NV) or
(UV) for the casts.
2) Perl 5.20 and later use SSize_t for array indices, so can cope with
up to SSize_t_max items in an array (if you have the memory).
3) To be able to actually return such result sets from sp_exec_query(),
I had to change the repalloc() in spi_printtup() to repalloc_huge().
--
"A disappointingly low fraction of the human race is,
at any given time, on fire." - Stig Sandbeck Mathisen
>From f6d38f1a5c7d6135dd5f580aa8ed38bb74162a0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= <ilmari@ilmari.org>
Date: Sun, 13 Mar 2016 01:21:43 +0000
Subject: [PATCH] Use correct types and limits for PL/Perl SPI query results
Perl's integers are pointer-sized, so can hold more than INT_MAX on LP64
platforms, and come in both signed (IV) and unsigned (UV). Floating
point values (NV) may also be larger than double.
Since Perl 5.19.4 array indices are SSize_t instead of I32, so allow up
to SSize_t_max on those versions. The limit is not imposed just by
av_extend's argument type, but all the array handling code, so remove
the speculative comment.
Finally, change spi_printtup() to use repalloc_huge() to be able to
return a tuple table of more than 1GiB.
---
src/backend/executor/spi.c | 2 +-
src/pl/plperl/plperl.c | 13 ++++---------
src/pl/plperl/plperl.h | 7 +++++++
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 3d04c23..fd94179 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1800,7 +1800,7 @@ spi_printtup(TupleTableSlot *slot, DestReceiver *self)
/* Double the size of the pointer array */
tuptable->free = tuptable->alloced;
tuptable->alloced += tuptable->free;
- tuptable->vals = (HeapTuple *) repalloc(tuptable->vals,
+ tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals,
tuptable->alloced * sizeof(HeapTuple));
}
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 269f7f3..d405179 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -3104,9 +3104,9 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed,
hv_store_string(result, "status",
cstr2sv(SPI_result_code_string(status)));
hv_store_string(result, "processed",
- (processed > (uint64) INT_MAX) ?
- newSVnv((double) processed) :
- newSViv((int) processed));
+ (processed > (uint64) UV_MAX) ?
+ newSVnv((NV) processed) :
+ newSVuv((UV) processed));
if (status > 0 && tuptable)
{
@@ -3114,12 +3114,7 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed,
SV *row;
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)
+ if (processed > AV_SIZE_MAX)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("query result has too many rows to fit in a Perl array")));
diff --git a/src/pl/plperl/plperl.h b/src/pl/plperl/plperl.h
index 9179bbd..2f376ee 100644
--- a/src/pl/plperl/plperl.h
+++ b/src/pl/plperl/plperl.h
@@ -100,4 +100,11 @@ void plperl_spi_freeplan(char *);
void plperl_spi_cursor_close(char *);
char *plperl_sv_to_literal(SV *, char *);
+/* Perl 5.19.4 changed array indices from I32 to SSize_t */
+#if PERL_BCDVERSION >= 0x5019004
+#define AV_SIZE_MAX ((uint64) SSize_t_MAX)
+#else
+#define AV_SIZE_MAX ((uint64) I32_MAX)
+#endif
+
#endif /* PL_PERL_H */
--
2.7.0
pgsql-hackers by date: