This patch is pretty trivial.
Another slightly less trivial but more useful version.
The issue is that there are 3 definitions of modulo, two of which are fine
(Knuth floored division and Euclidian), and the last one much less useful.
Alas, C (%) & SQL (MOD) choose the bad definition:-( I really need any of
the other two. The attached patch adds all versions, with "%" and "mod"
consistent with their C and SQL unfortunate counterparts, and "fmod" and
"emod" the sane ones.
Add modulo operator to pgbench.
This is useful to compute a permutation for tests with non uniform
accesses (exponential or gaussian), so as to avoid trivial correlations
between neighbour keys.
--
Fabien.
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index ad55c3c..377cc9b 100644
--- a/contrib/pgbench/pgbench.c
+++ b/contrib/pgbench/pgbench.c
@@ -1570,6 +1570,27 @@ top:
}
snprintf(res, sizeof(res), INT64_FORMAT, ope1 / ope2);
}
+ else if (strcmp(argv[3], "%") == 0 || strcmp(argv[3], "mod") == 0 ||
+ strcmp(argv[3], "fmod") == 0 || strcmp(argv[3], "emod") == 0)
+ {
+ int64_t remainder;
+ if (ope2 == 0)
+ {
+ fprintf(stderr, "%s: division by zero in modulo\n", argv[0]);
+ st->ecnt++;
+ return true;
+ }
+ /* remainder probably keeps the dividend sign in C */
+ remainder = ope1 % ope2;
+ /* floor modulo: adjust remainder sign wrt divisor sign */
+ if (strcmp(argv[3], "fmod") == 0 &&
+ ((ope2 < 0 && remainder > 0) || (ope2 > 0 && remainder < 0)))
+ remainder += ope2;
+ /* euclidian modulo: ensure positive remainder */
+ if (strcmp(argv[3], "emod") == 0 && remainder < 0)
+ remainder += llabs(ope2);
+ snprintf(res, sizeof(res), INT64_FORMAT, remainder);
+ }
else
{
fprintf(stderr, "%s: unsupported operator %s\n", argv[0], argv[3]);
diff --git a/doc/src/sgml/pgbench.sgml b/doc/src/sgml/pgbench.sgml
index b7d88f3..4b73911 100644
--- a/doc/src/sgml/pgbench.sgml
+++ b/doc/src/sgml/pgbench.sgml
@@ -735,7 +735,9 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
Each <replaceable>operand</> is either an integer constant or a
<literal>:</><replaceable>variablename</> reference to a variable
having an integer value. The <replaceable>operator</> can be
- <literal>+</>, <literal>-</>, <literal>*</>, or <literal>/</>.
+ <literal>+</>, <literal>-</>, <literal>*</>, <literal>/</>, <literal>%</>,
+ <literal>mod</> (dividend sign modulo), <literal>fmod</> (divisor sign modulo)
+ or <literal>emod</> (Euclidian modulo).
</para>
<para>
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers