v2-0004-pgbench-Modernize-integer-parsing-routine.patch
text/x-patch
Filename: v2-0004-pgbench-Modernize-integer-parsing-routine.patch
Type: text/x-patch
Part: 3
Message:
Re: 64 bit numbers vs format strings
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0004
Subject: pgbench: Modernize integer parsing routine.
| File | + | − |
|---|---|---|
| src/bin/pgbench/pgbench.c | 11 | 61 |
From f190083fbc4ea2b9752950bf37a78f61abad12a0 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 6 Dec 2024 09:31:16 +1300
Subject: [PATCH v2 4/5] pgbench: Modernize integer parsing routine.
strtoint64() is from pre-C99 times and had comments about scanf() not
being sure to handle long long. Even though C99 scanf() can do SCNi64,
it seems like we'd lose a bit of error reporting. A more obvious modern
drop-in is strtoi64(). Then strtoint64() can log the same errors as
before.
---
src/bin/pgbench/pgbench.c | 72 ++++++---------------------------------
1 file changed, 11 insertions(+), 61 deletions(-)
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index acf55eccafb..0a9d3eefc8f 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -1003,9 +1003,6 @@ is_an_int(const char *str)
/*
* strtoint64 -- convert a string to 64-bit integer
*
- * This function is a slightly modified version of pg_strtoint64() from
- * src/backend/utils/adt/numutils.c.
- *
* The function returns whether the conversion worked, and if so
* "*result" is set to the result.
*
@@ -1014,71 +1011,24 @@ is_an_int(const char *str)
bool
strtoint64(const char *str, bool errorOK, int64 *result)
{
- const char *ptr = str;
- int64 tmp = 0;
- bool neg = false;
-
- /*
- * Do our own scan, rather than relying on sscanf which might be broken
- * for long long.
- *
- * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate
- * value as a negative number.
- */
+ char *end;
- /* skip leading spaces */
- while (*ptr && isspace((unsigned char) *ptr))
- ptr++;
+ errno = 0;
+ *result = strtoi64(str, &end, 10);
- /* handle sign */
- if (*ptr == '-')
+ if (errno == ERANGE)
{
- ptr++;
- neg = true;
- }
- else if (*ptr == '+')
- ptr++;
-
- /* require at least one digit */
- if (unlikely(!isdigit((unsigned char) *ptr)))
- goto invalid_syntax;
-
- /* process digits */
- while (*ptr && isdigit((unsigned char) *ptr))
- {
- int8 digit = (*ptr++ - '0');
-
- if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) ||
- unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
- goto out_of_range;
+ if (!errorOK)
+ pg_log_error("value \"%s\" is out of range for type bigint", str);
+ return false;
}
-
- /* allow trailing whitespace, but not other trailing chars */
- while (*ptr != '\0' && isspace((unsigned char) *ptr))
- ptr++;
-
- if (unlikely(*ptr != '\0'))
- goto invalid_syntax;
-
- if (!neg)
+ if (str == end || *end != '\0')
{
- if (unlikely(tmp == PG_INT64_MIN))
- goto out_of_range;
- tmp = -tmp;
+ if (!errorOK)
+ pg_log_error("invalid input syntax for type bigint: \"%s\"", str);
+ return false;
}
-
- *result = tmp;
return true;
-
-out_of_range:
- if (!errorOK)
- pg_log_error("value \"%s\" is out of range for type bigint", str);
- return false;
-
-invalid_syntax:
- if (!errorOK)
- pg_log_error("invalid input syntax for type bigint: \"%s\"", str);
- return false;
}
/* convert string to double, detecting overflows/underflows */
--
2.48.1