diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index d5f242c..25b349d 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -967,7 +967,28 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval) fprintf(stderr, "division by zero\n"); return false; } - *retval = lval / rval; + /* + * INT64_MIN / -1 is problematic, since the result + * can't be represented on a two's-complement + * machine. Some machines produce INT64_MIN, some + * produce zero, some throw an exception. We can + * dodge the problem by recognizing that division + * by -1 is the same as negation. + */ + if (rval == -1) + { + *retval = -lval; + + /* overflow check (needed for INT64_MIN) */ + if (lval != 0 && (*retval < 0 == lval < 0)) + { + fprintf(stderr, "bigint out of range\n"); + return false; + } + } + else + *retval = lval / rval; + return true; case '%': @@ -976,7 +997,15 @@ evaluateExpr(CState *st, PgBenchExpr *expr, int64 *retval) fprintf(stderr, "division by zero\n"); return false; } - *retval = lval % rval; + /* + * Some machines throw a floating-point exception + * for INT64_MIN % -1, the correct answer being + * zero in any case. + */ + if (rval == -1) + *retval = 0; + else + *retval = lval % rval; return true; }