Re: Fix runtime errors from -fsanitize=undefined

2019-07-05 Thread Raúl Marín Rodríguez
> 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

2019-03-05 Thread Raúl Marín Rodríguez
> 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

2019-02-08 Thread Raúl Marín Rodríguez
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

2019-01-22 Thread Raúl Marín Rodríguez
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

2019-01-18 Thread Raúl Marín Rodríguez
> 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

2019-01-18 Thread Raúl Marín Rodríguez
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

2019-01-18 Thread Raúl Marín Rodríguez
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

2018-11-14 Thread Raúl Marín Rodríguez
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

2018-11-14 Thread Raúl Marín Rodríguez
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?

2018-08-09 Thread Raúl Marín Rodríguez
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

2017-12-26 Thread Raúl Marín Rodríguez
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

2017-12-22 Thread Raúl Marín Rodríguez
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

2017-12-21 Thread Raúl Marín Rodríguez
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

2017-12-05 Thread Raúl Marín Rodríguez
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

2017-12-04 Thread Raúl Marín Rodríguez
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

2017-12-01 Thread Raúl Marín Rodríguez
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

2017-12-01 Thread Raúl Marín Rodríguez
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