Re: Fix runtime errors from -fsanitize=undefined
> This sanitizer has found real problems in the past. By removing these > trivial issues we can then set up a build farm animal or similar to > automatically check for any new issues. We have done exactly this in postgis with 2 different jobs (gcc and clang) and, even though it doesn't happen too often, it's really satisfying when it detects these issues automatically. -- Raúl Marín Rodríguez carto.com
Re: Re: [PATCH] pgbench tap tests fail if the path contains a perl special character
> Marking the patch as either Ready for Committer or Waiting on Author will help move things along. Thanks for the heads-up, I've retested it again and it applies cleanly on top of master and addresses the issue. I've moved it to `Ready for Committer`. -- Raúl Marín Rodríguez carto.com
Re: [PATCH] pgbench tap tests fail if the path contains a perl special character
Hi, Any way I can help to get this commited? Should we add this to the commitfest? Regards, -- Raúl Marín Rodríguez carto.com
Re: [PATCH] pgbench tap tests fail if the path contains a perl special character
Hi, > - works around pgbench command splitting on spaces, >if postgres sources are in a strangely named directory… >I tested within a directory named "pg .* dir". I've also tested it with the initial case (including a +) and it works. -- Raúl Marín Rodríguez carto.com
Re: [PATCH] pgbench tap tests fail if the path contains a perl special character
> Pushed with that correction. Thanks a lot! -- Raúl Marín Rodríguez carto.com
Re: [PATCH] pgbench tap tests fail if the path contains a perl special character
Hi, > Fun. But is that really the only place that fails? Yes, other than this it builds flawlessly. > This does not look right to me: glob has a different set of special > characters than regexes, no? The issue itself manifests in the grep call, not in glob, but I tried using `quotemeta` only for grep without success (probably because I didn't know how to properly call `quotemeta` over @logs. This is the first time I do anything in perl beyond adding some simple tap tests, so this could be me not knowing how to deal with it properly. I used this small script to understand perl's behaviour: ``` $ cat a.pl #!/usr/bin/perl use strict; use warnings; my @prefix = '~/postgres+/001_pgbench_log_2.20745'; my @quoted_prefix = quotemeta(@prefix); my @found1 = grep(/^@prefix\.\d+(\.\d+)?$/, "@prefix.20745"); my @found2 = grep(/^@prefix\.\d+(\.\d+)?$/, "@quoted_prefix.20745"); my @found3 = grep(/^@quoted_prefix\.\d+(\.\d+)?$/, "@prefix.20745"); my @found4 = grep(/^@quoted_prefix\.\d+(\.\d+)?$/, "@quoted_prefix.20745"); print "1: @found1\n"; print "2: @found2\n"; print "3: @found3\n"; print "4: @found4\n"; $ perl a.pl 1: 2: 3: 4: 1.20745 ``` Regards, -- Raúl Marín Rodríguez carto.com
[PATCH] pgbench tap tests fail if the path contains a perl special character
Hi, As mentioned in the subject, if the $PATH where you are building postgres contains a perl's special character [1], for example a `+`, pgbench's tap tests will fail. The outputs looks something like this (full at [2]): ``` # Failed test 'file name format' # at t/001_pgbench_with_server.pl line 805. # Failed test 'file name format' # at t/001_pgbench_with_server.pl line 805. # Looks like you failed 2 tests of 312. t/001_pgbench_with_server.pl .. Dubious, test returned 2 (wstat 512, 0x200) Failed 2/312 subtests t/002_pgbench_no_server.pl ok ``` This error affects both PG11 and master, and a way to reproduce it is by renaming the source folder from `postgresql` to `postgresql+XXX`. I'm attaching a patch to fix this by using quotemeta [3]. It's generated from master and also applies to REL_11_STABLE. 1 - http://jkorpela.fi/perl/regexp.html 2 - https://launchpadlibrarian.net/406634533/buildlog_ubuntu-xenial-amd64.postgresql-11_11.1.1+carto-2_BUILDING.txt.gz 3 - https://perldoc.perl.org/functions/quotemeta.html Regards, -- Raúl Marín Rodríguez carto.com diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index c87748086a..eb126d2525 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -879,9 +879,10 @@ sub check_pgbench_logs my ($prefix, $nb, $min, $max, $re) = @_; - my @logs = glob "$prefix.*"; +my @quoted_prefix = quotemeta($prefix); + my @logs = glob "@quoted_prefix.*"; ok(@logs == $nb, "number of log files"); - ok(grep(/^$prefix\.\d+(\.\d+)?$/, @logs) == $nb, "file name format"); + ok(grep(/^@quoted_prefix\.\d+(\.\d+)?$/, @logs) == $nb, "Failed to match file format. Looked for (@quoted_prefix) in (@logs)"); my $log_number = 0; for my $log (sort @logs)
Re: [PATCH] Memory leak in pg_config
Hi, I understand it, as I said it's not an issue; just annoying when using sanitizers. Thanks for the information. -- Raúl Marín Rodríguez carto.com
[PATCH] Memory leak in pg_config
Hi, I've been trying to run Postgis regress tests under Clang sanitizers and one of the issues I'm facing is the constant stream of errors during the `configure` step coming from calls to `pg_config`. Example: ``` $ pg_config --cc clang = ==14521==ERROR: LeakSanitizer: detected memory leaks Direct leak of 368 byte(s) in 1 object(s) allocated from: #0 0x55de20d161d9 in malloc (/usr/bin/pg_config+0xf81d9) [...] SUMMARY: AddressSanitizer: 2610 byte(s) leaked in 47 allocation(s). ``` The leaked memory is part of the `configdata` array which isn't freed before exiting. It doesn't have any long term impact but it's annoying. A similar thing happens in the `pg_config` SQL function. Since the memory will be released at the end of the transaction, releasing it is optional but I've done it anyway. I'm attaching a the patch with the changes. Greetings, Greetings, -- Raúl Marín Rodríguez carto.com From 0d35d7a21b87554df7ef27b70dcf7e4ea512699f Mon Sep 17 00:00:00 2001 From: Raul Marin Date: Wed, 14 Nov 2018 09:08:50 +0100 Subject: [PATCH] pg_config: Avoid leaking configdata --- src/backend/utils/misc/pg_config.c | 1 + src/bin/pg_config/pg_config.c | 4 src/common/config_info.c | 15 ++- src/include/common/config_info.h | 2 ++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/misc/pg_config.c b/src/backend/utils/misc/pg_config.c index aa434bc3ab..62d1aea287 100644 --- a/src/backend/utils/misc/pg_config.c +++ b/src/backend/utils/misc/pg_config.c @@ -78,6 +78,7 @@ pg_config(PG_FUNCTION_ARGS) tuple = BuildTupleFromCStrings(attinmeta, values); tuplestore_puttuple(tupstore, tuple); } + free_configdata(configdata, configdata_len); /* * no longer need the tuple descriptor reference created by diff --git a/src/bin/pg_config/pg_config.c b/src/bin/pg_config/pg_config.c index a341b756de..c53a802422 100644 --- a/src/bin/pg_config/pg_config.c +++ b/src/bin/pg_config/pg_config.c @@ -160,6 +160,7 @@ main(int argc, char **argv) { for (i = 0; i < configdata_len; i++) printf("%s = %s\n", configdata[i].name, configdata[i].setting); + free_configdata(configdata, configdata_len); exit(0); } @@ -180,9 +181,12 @@ main(int argc, char **argv) fprintf(stderr, _("%s: invalid argument: %s\n"), progname, argv[i]); advice(); + free_configdata(configdata, configdata_len); exit(1); } } + free_configdata(configdata, configdata_len); + return 0; } diff --git a/src/common/config_info.c b/src/common/config_info.c index 55e688e656..f8da71c598 100644 --- a/src/common/config_info.c +++ b/src/common/config_info.c @@ -27,7 +27,7 @@ * get_configdata(const char *my_exec_path, size_t *configdata_len) * * Get configure-time constants. The caller is responsible - * for pfreeing the result. + * for pfreeing the result [free_configdata] */ ConfigData * get_configdata(const char *my_exec_path, size_t *configdata_len) @@ -203,3 +203,16 @@ get_configdata(const char *my_exec_path, size_t *configdata_len) return configdata; } + + +void +free_configdata(ConfigData *configdata, size_t configdata_len) +{ + int i; + for (i = 0; i < configdata_len; i++) + { + pfree(configdata[i].name); + pfree(configdata[i].setting); + } + pfree(configdata); +} diff --git a/src/include/common/config_info.h b/src/include/common/config_info.h index 72014a915a..26f85e86a9 100644 --- a/src/include/common/config_info.h +++ b/src/include/common/config_info.h @@ -18,4 +18,6 @@ typedef struct ConfigData extern ConfigData *get_configdata(const char *my_exec_path, size_t *configdata_len); +extern void free_configdata(ConfigData *configdata, size_t configdata_len); + #endif /* COMMON_CONFIG_INFO_H */ -- 2.19.1
Do all rows from a set have the same TupleDesc?
Hi, I have an user defined aggregate (Postgis' St_AsMVT) that receives rows as input and I was wondering if all these tuples have the same TupleDesc. In case it's important, here is how it's normally called: ``` SELECT St_AsMVT(q) FROM ( SELECT * FROM tilertest.tract9double ) q; ``` The idea behind this question is that, if this were true, I could cache some information (number of attributes, oids, some internal stuff related to each attribute) until the end of the aggregation to avoid having to retrieve or calculate them for each one of the rows. All the tests I've made seem to confirm this is true, but I was wondering if there is any guarantee. Regards -- *Raúl Marín Rodríguez *carto.com
Re: [HACKERS] pow support for pgbench
Hi, I've implemented the overflow checks and made some benchmarks and the ipow() version became slower except with some specific inputs (base 0 for example). It's true that the new auxiliary functions could be optimized, but I don't think it makes sense to keep working on them just to match pow() speed. I'm attaching both patches in case someone wants to have a look but I would go with the simpler solution (pgbench_pow_v10.patch). Regards, -- *Raúl Marín Rodríguez *carto.com From 28bc71f657fa967bafc03c015e5e2405c427a711 Mon Sep 17 00:00:00 2001 From: Raul Marin <rmrodrig...@cartodb.com> Date: Thu, 21 Dec 2017 20:28:02 +0100 Subject: [PATCH] Add pow() support to pgbench --- doc/src/sgml/ref/pgbench.sgml| 7 +++ src/bin/pgbench/exprparse.y | 6 ++ src/bin/pgbench/pgbench.c| 16 src/bin/pgbench/pgbench.h| 3 ++- src/bin/pgbench/t/001_pgbench_with_server.pl | 22 +- 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index 4431fc3eb7..1519fe78ef 100644 --- a/doc/src/sgml/ref/pgbench.sgml +++ b/doc/src/sgml/ref/pgbench.sgml @@ -1069,6 +1069,13 @@ pgbench options d pi() 3.14159265358979323846 + + pow(x, y), power(x, y) + double + exponentiation + pow(2.0, 10), power(2.0, 10) + 1024.0 + random(lb, ub) integer diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y index 25d5ad48e5..74ffe5e7a7 100644 --- a/src/bin/pgbench/exprparse.y +++ b/src/bin/pgbench/exprparse.y @@ -194,6 +194,12 @@ static const struct { "random_zipfian", 3, PGBENCH_RANDOM_ZIPFIAN }, + { + "pow", 2, PGBENCH_POW + }, + { + "power", 2, PGBENCH_POW + }, /* keep as last array element */ { NULL, 0, 0 diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 7ce6f607f5..5b444765dd 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -1850,6 +1850,22 @@ evalFunc(TState *thread, CState *st, return true; } + case PGBENCH_POW: + { +PgBenchValue *lval = [0]; +PgBenchValue *rval = [1]; + +Assert(nargs == 2); + +if (!coerceToDouble(lval, ) || + !coerceToDouble(rval, )) + return false; + +setDoubleValue(retval, pow(ld, rd)); + +return true; + } + default: /* cannot get here */ Assert(0); diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h index 83fee1ae74..0e92882a4c 100644 --- a/src/bin/pgbench/pgbench.h +++ b/src/bin/pgbench/pgbench.h @@ -76,7 +76,8 @@ typedef enum PgBenchFunction PGBENCH_RANDOM, PGBENCH_RANDOM_GAUSSIAN, PGBENCH_RANDOM_EXPONENTIAL, - PGBENCH_RANDOM_ZIPFIAN + PGBENCH_RANDOM_ZIPFIAN, + PGBENCH_POW } PgBenchFunction; typedef struct PgBenchExpr PgBenchExpr; diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index e3cdf28628..9cbeb2fc11 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -232,7 +232,17 @@ pgbench( qr{command=19.: double 19\b}, qr{command=20.: double 20\b}, qr{command=21.: int 9223372036854775807\b}, - qr{command=23.: int [1-9]\b}, ], + qr{command=23.: int [1-9]\b}, + qr{command=24.: double -27\b}, + qr{command=25.: double 1024\b}, + qr{command=26.: double 1\b}, + qr{command=27.: double 1\b}, + qr{command=28.: double -0.125\b}, + qr{command=29.: double -0.125\b}, + qr{command=30.: double -0.00032\b}, + qr{command=31.: double 8.50705917302346e\+37\b}, + qr{command=32.: double 1e\+30\b}, + ], 'pgbench expressions', { '001_pgbench_expressions' => q{-- integer functions \set i1 debug(random(1, 100)) @@ -264,6 +274,16 @@ pgbench( \set i1 0 -- yet another integer function \set id debug(random_zipfian(1, 9, 1.3)) +--- pow and power +\set poweri debug(pow(-3,3)) +\set powerd debug(pow(2.0,10)) +\set poweriz debug(pow(0,0)) +\set powerdz debug(pow(0.0,0.0)) +\set powernegi debug(pow(-2,-3)) +\set powernegd debug(pow(-2.0,-3.0)) +\set powernegd2 debug(power(-5.0,-5.0)) +\set powerov debug(pow(9223372036854775807, 2)) +\set powerov2 debug(pow(10,30)) } }); # backslash commands -- 2.15.1 From 6cb8fb1a3eaffe680b85913b0acf0068dcb0d2a7 Mon Sep 17 00:00:00 2001 From: Raul Marin <rmrodrig...@cartodb.com> Date: Thu, 21 Dec 2017 20:28:02 +0100 Subject: [PATCH] Add pow() support to pgbench --- doc/src/sgml/ref/pgbench.sgml| 7 ++ src/bin/pgbench/exprparse.y | 6 ++ src/bin/pgbench/pgbench.c| 100 +++ src/bin/pgbench/pgbench.h| 3 +- src/bin/pgbench/t/001_pgbench_with_server.pl | 22 +- 5 files changed, 136 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgb
Re: [HACKERS] pow support for pgbench
Hi Fabien, Thanks for the review. If a double is always returned, I'm wondering whether keeping the ipow > version makes much sense: In case of double loss of precision, the > precision is lost, too bad, and casting back to int won't bring it back. I've kept it because knowing that both are ints enables not making a lot of checks (done in math.h pow) so it's way faster. In my system it's 2-3ns vs ~40ns. I'm willing to settle for using just pow() if that makes it clearer. In the doc, I'm not sure that "Numeric" brings anything. "Exponentiation" > would be enough. Done. Also, in pg I just noticed that POW is a shorthand for POWER. Maybe both > should be supported? Or not. I've never used power instead of pow, but I've added for compatibility shake. Attached the updated patch. On Thu, Dec 21, 2017 at 10:48 PM, Fabien COELHO <coe...@cri.ensmp.fr> wrote: > > Hello Raúl, > > v7 needs a rebase. >>> >>> Also, you might try to produce a version which is compatible with >>> Robert's >>> constraints. >>> >> > My 0.02€ on this new version: Applies cleanly, compiles and works. > > I cannot say that I like it more than the previous version. > > If a double is always returned, I'm wondering whether keeping the ipow > version makes much sense: In case of double loss of precision, the > precision is lost, too bad, and casting back to int won't bring it back. > > In the doc, I'm not sure that "Numeric" brings anything. "Exponentiation" > would be enough. > > Also, in pg I just noticed that POW is a shorthand for POWER. Maybe both > should be supported? Or not. > > -- > Fabien. -- *Raúl Marín Rodríguez *carto.com From 58463d2751c016a68410d5357625bf3d7f519ca2 Mon Sep 17 00:00:00 2001 From: Raul Marin <rmrodrig...@cartodb.com> Date: Thu, 21 Dec 2017 20:28:02 +0100 Subject: [PATCH] Add pow() support to pgbench --- doc/src/sgml/ref/pgbench.sgml| 7 src/bin/pgbench/exprparse.y | 6 +++ src/bin/pgbench/pgbench.c| 60 src/bin/pgbench/pgbench.h| 3 +- src/bin/pgbench/t/001_pgbench_with_server.pl | 18 - 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index 4431fc3eb7..1519fe78ef 100644 --- a/doc/src/sgml/ref/pgbench.sgml +++ b/doc/src/sgml/ref/pgbench.sgml @@ -1069,6 +1069,13 @@ pgbench options d pi() 3.14159265358979323846 + + pow(x, y), power(x, y) + double + exponentiation + pow(2.0, 10), power(2.0, 10) + 1024.0 + random(lb, ub) integer diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y index 25d5ad48e5..74ffe5e7a7 100644 --- a/src/bin/pgbench/exprparse.y +++ b/src/bin/pgbench/exprparse.y @@ -194,6 +194,12 @@ static const struct { "random_zipfian", 3, PGBENCH_RANDOM_ZIPFIAN }, + { + "pow", 2, PGBENCH_POW + }, + { + "power", 2, PGBENCH_POW + }, /* keep as last array element */ { NULL, 0, 0 diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 7ce6f607f5..f1c1e568e1 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -911,6 +911,25 @@ getZipfianRand(TState *thread, int64 min, int64 max, double s) : computeHarmonicZipfian(thread, n, s)); } +/* Faster power function for integer values and exp >= 0 */ +static int64 +ipow(int64 base, int64 exp) +{ + int64 result = 1; + + Assert(exp >= 0); + + while (exp) + { + if (exp & 1) + result *= base; + exp >>= 1; + base *= base; + } + + return result; +} + /* * Initialize the given SimpleStats struct to all zeroes */ @@ -1850,6 +1869,47 @@ evalFunc(TState *thread, CState *st, return true; } + case PGBENCH_POW: + { +PgBenchValue *lval = [0]; +PgBenchValue *rval = [1]; + +Assert(nargs == 2); + +/* + * If both operands are int and exp >= 0 use + * the faster ipow() function, else use pow() + */ +if (lval->type == PGBT_INT && + rval->type == PGBT_INT) +{ + + int64 li, +ri; + + if (!coerceToInt(lval, ) || + !coerceToInt(rval, )) + return false; + + if (ri >= 0) + setDoubleValue(retval, ipow(li, ri)); + else + setDoubleValue(retval, pow(li, ri)); +} +else +{ + double ld, +rd; + + if (!coerceToDouble(lval, ) || + !coerceToDouble(rval, )) + return false; + + setDoubleValue(retval, pow(ld, rd)); +} +return true; + } + default: /* cannot get here */ Assert(0); diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h index 83fee1ae74..0e92882a4c 100644 --- a/src/bin/pgbench/pgbench.h +++ b/src/bin/p
Re: [HACKERS] pow support for pgbench
Hi, Rebased the patch on top of current master/HEAD and changed to always return double. On Thu, Dec 14, 2017 at 12:48 PM, Fabien COELHO <coe...@cri.ensmp.fr> wrote: > > Fixed in the attached patch. >> > > v7 needs a rebase. > > Also, you might try to produce a version which is compatible with Robert's > constraints. > > -- > Fabien. > -- *Raúl Marín Rodríguez *carto.com From 0b43116dc68cbe46d5f5caa9ba10f36cda188949 Mon Sep 17 00:00:00 2001 From: Raul Marin <rmrodrig...@cartodb.com> Date: Thu, 21 Dec 2017 20:28:02 +0100 Subject: [PATCH] Add pow() support to pgbench --- doc/src/sgml/ref/pgbench.sgml| 7 src/bin/pgbench/exprparse.y | 3 ++ src/bin/pgbench/pgbench.c| 60 src/bin/pgbench/pgbench.h| 3 +- src/bin/pgbench/t/001_pgbench_with_server.pl | 16 +++- 5 files changed, 87 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index 4431fc3eb7..6f7c640db0 100644 --- a/doc/src/sgml/ref/pgbench.sgml +++ b/doc/src/sgml/ref/pgbench.sgml @@ -1069,6 +1069,13 @@ pgbench options d pi() 3.14159265358979323846 + + pow(x, y) + double + Numeric exponentiation + pow(2.0, 10) + 1024.0 + random(lb, ub) integer diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y index 25d5ad48e5..89e1a3b14f 100644 --- a/src/bin/pgbench/exprparse.y +++ b/src/bin/pgbench/exprparse.y @@ -194,6 +194,9 @@ static const struct { "random_zipfian", 3, PGBENCH_RANDOM_ZIPFIAN }, + { + "pow", 2, PGBENCH_POW + }, /* keep as last array element */ { NULL, 0, 0 diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 7ce6f607f5..f1c1e568e1 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -911,6 +911,25 @@ getZipfianRand(TState *thread, int64 min, int64 max, double s) : computeHarmonicZipfian(thread, n, s)); } +/* Faster power function for integer values and exp >= 0 */ +static int64 +ipow(int64 base, int64 exp) +{ + int64 result = 1; + + Assert(exp >= 0); + + while (exp) + { + if (exp & 1) + result *= base; + exp >>= 1; + base *= base; + } + + return result; +} + /* * Initialize the given SimpleStats struct to all zeroes */ @@ -1850,6 +1869,47 @@ evalFunc(TState *thread, CState *st, return true; } + case PGBENCH_POW: + { +PgBenchValue *lval = [0]; +PgBenchValue *rval = [1]; + +Assert(nargs == 2); + +/* + * If both operands are int and exp >= 0 use + * the faster ipow() function, else use pow() + */ +if (lval->type == PGBT_INT && + rval->type == PGBT_INT) +{ + + int64 li, +ri; + + if (!coerceToInt(lval, ) || + !coerceToInt(rval, )) + return false; + + if (ri >= 0) + setDoubleValue(retval, ipow(li, ri)); + else + setDoubleValue(retval, pow(li, ri)); +} +else +{ + double ld, +rd; + + if (!coerceToDouble(lval, ) || + !coerceToDouble(rval, )) + return false; + + setDoubleValue(retval, pow(ld, rd)); +} +return true; + } + default: /* cannot get here */ Assert(0); diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h index 83fee1ae74..0e92882a4c 100644 --- a/src/bin/pgbench/pgbench.h +++ b/src/bin/pgbench/pgbench.h @@ -76,7 +76,8 @@ typedef enum PgBenchFunction PGBENCH_RANDOM, PGBENCH_RANDOM_GAUSSIAN, PGBENCH_RANDOM_EXPONENTIAL, - PGBENCH_RANDOM_ZIPFIAN + PGBENCH_RANDOM_ZIPFIAN, + PGBENCH_POW } PgBenchFunction; typedef struct PgBenchExpr PgBenchExpr; diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index e3cdf28628..031b97fc54 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -232,7 +232,14 @@ pgbench( qr{command=19.: double 19\b}, qr{command=20.: double 20\b}, qr{command=21.: int 9223372036854775807\b}, - qr{command=23.: int [1-9]\b}, ], + qr{command=23.: int [1-9]\b}, + qr{command=24.: double -27\b}, + qr{command=25.: double 1024\b}, + qr{command=26.: double 1\b}, + qr{command=27.: double 1\b}, + qr{command=28.: double -0.125\b}, + qr{command=29.: double -0.125\b}, + ], 'pgbench expressions', { '001_pgbench_expressions' => q{-- integer functions \set i1 debug(random(1, 100)) @@ -264,6 +271,13 @@ pgbench( \set i1 0 -- yet another integer function \set id debug(random_zipfian(1, 9, 1.3)) +--- pow() operator +\set poweri debug(pow(-3,3)) +\set powerd debug(pow(2.0,10)) +\set poweriz debug(pow(0,0)) +\set powerdz debug(pow(0.0,0.0)) +\set powernegi debug(pow(-2,-3)) +\set powernegd debug(pow(-2.0,-3.0)) } }); # backslash commands -- 2.15.1
Re: [HACKERS] pow support for pgbench
Hi all, I've been giving a thought about this and I think we could reach the compromise of having a single function with 2 overloads: * pow(double, double) -> double: Uses C pow(). * pow(int, int) -> double: Uses ipow() for positive exponents, and pow() for negative exponents. In both cases we'd return a double but we use the fast ipow if it's possible (which can be 20x faster), so at the cost of an extra cast if you need an int, we'd have a consistent API. Would this be acceptable?
Re: [HACKERS] pgbench more operators & functions
Hi, > Regenerated v15 that applies cleanly on head. No changes. I'm not sure why it wasn't failing before, but I have issues building the doc: +are built into pgbench Missing '/' to close the xref + 1 3 Expecting ';' as the previous use () On Fri, Dec 1, 2017 at 1:57 PM, Fabien COELHO <coe...@cri.ensmp.fr> wrote: > > Here is a v13. No code changes, but TAP tests added to maintain pgbench >>>>> coverage to green. >>>>> >>>> >> Here is a v14, which is just a rebase after the documentation xml-ization. >> > > Regenerated v15 that applies cleanly on head. No changes. > > -- > Fabien. -- *Raúl Marín Rodríguez *carto.com
Re: [HACKERS] pow support for pgbench
Hi Fabien, The idea is that it would be relative to the "more functions and operators" > patch, but I guess this is too much for people checking, so I'm fine with > having it with the current base. > I tried applying the last "more functions and operators" patch (pgbench-more-ops-funcs-14.patch) but it also stopped applying cleanly so I decided to go for master to avoid having too many issues. Let me know if you rework that patch and I'll be happy to rebase mine on top. -- *Raúl Marín Rodríguez *carto.com
Re: [HACKERS] pow support for pgbench
Hi, I've rebased the patch so it can be applied cleanly on top of current master. On Fri, Dec 1, 2017 at 3:55 AM, Michael Paquier <michael.paqu...@gmail.com> wrote: > On Tue, Nov 7, 2017 at 1:34 AM, Fabien COELHO <coe...@cri.ensmp.fr> wrote: > > Let's now hope that a committer gets around to consider these patch some > > day. > > Which is not the case yet, so moved to CF 2018-01. Please note that > the patch proposed does not apply anymore, so its status is changed to > "waiting on author" for a rebase. > -- > Michael > -- *Raúl Marín Rodríguez *carto.com From b12a7a37b1af1ede1aa9d5d88d0918808c54e19f Mon Sep 17 00:00:00 2001 From: Raul Marin <rmrodrig...@cartodb.com> Date: Fri, 1 Dec 2017 10:49:17 +0100 Subject: [PATCH] Add pow() support to pgbench --- doc/src/sgml/ref/pgbench.sgml| 7 src/bin/pgbench/exprparse.y | 3 ++ src/bin/pgbench/pgbench.c| 62 src/bin/pgbench/pgbench.h| 3 +- src/bin/pgbench/t/001_pgbench_with_server.pl | 16 ++- 5 files changed, 89 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index 94b495e606..769e604dd6 100644 --- a/doc/src/sgml/ref/pgbench.sgml +++ b/doc/src/sgml/ref/pgbench.sgml @@ -1099,6 +1099,13 @@ pgbench options d sqrt(2.0) 1.414213562 + + pow(x, y) + integer if x and y are integers and y >= 0, else double + Numeric exponentiation + pow(2.0, 10) + 1024.0 + diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y index b3a2d9bfd3..4db3b215ab 100644 --- a/src/bin/pgbench/exprparse.y +++ b/src/bin/pgbench/exprparse.y @@ -191,6 +191,9 @@ static const struct { "random_exponential", 3, PGBENCH_RANDOM_EXPONENTIAL }, + { + "pow", 2, PGBENCH_POW + }, /* keep as last array element */ { NULL, 0, 0 diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index bd96eae5e6..5a5197cf63 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -746,6 +746,27 @@ getPoissonRand(TState *thread, int64 center) return (int64) (-log(uniform) * ((double) center) + 0.5); } + /* + * pow() for integer values with exp >= 0. Matches SQL pow() behaviour + */ +static int64 +ipow(int64 base, int64 exp) +{ + int64 result = 1; + + Assert(exp >= 0); + + while (exp) + { + if (exp & 1) + result *= base; + exp >>= 1; + base *= base; + } + + return result; +} + /* * Initialize the given SimpleStats struct to all zeroes */ @@ -1673,6 +1694,47 @@ evalFunc(TState *thread, CState *st, return true; } + case PGBENCH_POW: + { +PgBenchValue *lval = [0]; +PgBenchValue *rval = [1]; + +Assert(nargs == 2); + +/* + * If both operands are int and exp >= 0 use + * the ipow() function, else use pow() + */ +if (lval->type == PGBT_INT && + rval->type == PGBT_INT) +{ + + int64 li, +ri; + + if (!coerceToInt(lval, ) || + !coerceToInt(rval, )) + return false; + + if (ri >= 0) + setIntValue(retval, ipow(li, ri)); + else + setDoubleValue(retval, pow(li, ri)); +} +else +{ + double ld, +rd; + + if (!coerceToDouble(lval, ) || + !coerceToDouble(rval, )) + return false; + + setDoubleValue(retval, pow(ld, rd)); +} +return true; + } + default: /* cannot get here */ Assert(0); diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h index fd428af274..e0132b5fcf 100644 --- a/src/bin/pgbench/pgbench.h +++ b/src/bin/pgbench/pgbench.h @@ -75,7 +75,8 @@ typedef enum PgBenchFunction PGBENCH_SQRT, PGBENCH_RANDOM, PGBENCH_RANDOM_GAUSSIAN, - PGBENCH_RANDOM_EXPONENTIAL + PGBENCH_RANDOM_EXPONENTIAL, + PGBENCH_POW } PgBenchFunction; typedef struct PgBenchExpr PgBenchExpr; diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index c095881312..fcb30cdde5 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -231,7 +231,14 @@ pgbench( qr{command=18.: double 18\b}, qr{command=19.: double 19\b}, qr{command=20.: double 20\b}, - qr{command=21.: int 9223372036854775807\b}, ], + qr{command=21.: int 9223372036854775807\b}, + qr{command=23.: int -27\b}, + qr{command=24.: double 1024\b}, + qr{command=25.: int 1\b}, + qr{command=26.: double 1\b}, + qr{command=27.: double -0.125\b}, + qr{command=28.: double -0.125\b}, +], 'pgbench expressions', { '001_pgbench_expressions' => q{-- integer functions \set i1 debug(random(1, 100)) @@ -261,6 +268,13 @@ pgbench( \set maxint debug(:minint - 1) -- reset a variable \set i1 0 +--- pow() operator +\set poweri debug(pow(-3,3)) +\set pow