Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-28 Thread Justin Pryzby
On Sat, Mar 28, 2020 at 07:14:23PM +0100, Christoph Zwerschke wrote:
> Am 28.03.2020 um 18:56 schrieb Justin Pryzby:
> > Maybe that should be --with-ssl-info ?  I found this:
> 
> Not sure about that. In the context of setup.py and negative_opt, I only see
> the 'no-' pattern being followed. Also, this is backward compatible.

Okay.  Better to be backwards compatible with itself than compatible with
something else.

-- 
Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-28 Thread Christoph Zwerschke

Am 28.03.2020 um 18:56 schrieb Justin Pryzby:
> Maybe that should be --with-ssl-info ?  I found this:

Not sure about that. In the context of setup.py and negative_opt, I only 
see the 'no-' pattern being followed. Also, this is backward compatible.


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-28 Thread Justin Pryzby
On Sat, Mar 28, 2020 at 06:24:12PM +0100, Christoph Zwerschke wrote:
> Am 28.03.2020 um 16:21 schrieb Justin Pryzby:
> > Also, you have every option defaulting to try, with the only consequence of 
> > an
> > unsupported PG version being a warning.  I mentioned that packages (at 
> > least in
> > the past for Debian) were encouraged to compile with --enable-foo 
> > --enable-bar..
> > ..such that a packages that was *expected* to compile again libfoo would 
> > fail
> > loudly at the compile stage if it wasn't there or was somehow broken.
> 
> Thanks for the quick feedback, Justin.
> 
> I have addressed both of your points in 
> https://github.com/PyGreSQL/PyGreSQL/commit/03858234c9077ea7e492a4bbd0664b9fad74b70d

 python setup.py build_ext --ssl-info 

Maybe that should be --with-ssl-info ?  I found this:
https://sourceware.org/autobook/autobook/autobook_14.html
|Using ‘--with-package=no’ is synonymous with ‘--without-package’ which is 
described below.

-- 
Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-28 Thread Christoph Zwerschke

Am 28.03.2020 um 16:21 schrieb Justin Pryzby:

Also, you have every option defaulting to try, with the only consequence of an
unsupported PG version being a warning.  I mentioned that packages (at least in
the past for Debian) were encouraged to compile with --enable-foo --enable-bar..
..such that a packages that was *expected* to compile again libfoo would fail
loudly at the compile stage if it wasn't there or was somehow broken.


Thanks for the quick feedback, Justin.

I have addressed both of your points in 
https://github.com/PyGreSQL/PyGreSQL/commit/03858234c9077ea7e492a4bbd0664b9fad74b70d


Better?

-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-28 Thread Justin Pryzby
On Sat, Mar 28, 2020 at 03:50:57PM +0100, Christoph Zwerschke wrote:
> Ok, I found that distutils even has a way to define "negative" options and
> used it in setup.py now:
> 
> Please have a look at: 
> https://github.com/PyGreSQL/PyGreSQL/commit/4b88231afd6bdfb40dca20780cdf006fe2346ea8

+self.escaping_funcs = True
+self.ssl_info = True


+ If the installed PostgreSQL version does not support some features, you will
+ see a warning during installation, and these feature will not be enabled, so 
...

=> I would change "during installation" to "during setup.py build phase" or 
something.
To me, "installation" reads as "installing a binary package".

Also, you have every option defaulting to try, with the only consequence of an
unsupported PG version being a warning.  I mentioned that packages (at least in
the past for Debian) were encouraged to compile with --enable-foo --enable-bar..
..such that a packages that was *expected* to compile again libfoo would fail
loudly at the compile stage if it wasn't there or was somehow broken.

-- 
Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-28 Thread Christoph Zwerschke
Ok, I found that distutils even has a way to define "negative" options 
and used it in setup.py now:


Please have a look at: 
https://github.com/PyGreSQL/PyGreSQL/commit/4b88231afd6bdfb40dca20780cdf006fe2346ea8


Let me know what you think about this change.

-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-25 Thread Christoph Zwerschke



Am 25.03.2020 um 12:28 schrieb Justin Pryzby:

I think (1) is more common, I think that's what autoconf and gnu
tools use.
In that case, maybe we should use enable/disable or with/without as 
prefixes, like autotools? But I think it's not very common as setup 
option. Also, by using the old option name and just adding the "no-" 
variant, we would stay backward compatible.


-- Christoph


___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-25 Thread Justin Pryzby
On Wed, Mar 25, 2020 at 12:25:12PM +0100, Christoph Zwerschke wrote:
> Am 25.03.2020 um 10:34 schrieb Justin Pryzby:
> > I think I would leave the "positive" variable names, and *add* negative 
> > forms
> > of the commandline options.  --no-foo and/or --foo=no
> 
> 1) Either two options --escaping-funcs and --no-escaping-funcs, both without
> arguments or
> 2) one option --escaping funcs with a mandatory boolean argument
> 
> In both cases, when we set self.escaping_funcs = None in initialize_options,
> we can implement the ternary on/off/default.
> 
> Not sure whether 1) or 2) is better, what do you think?

I think (1) is more common, I think that's what autoconf and gnu tools use.

-- 
Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-25 Thread Christoph Zwerschke

Am 25.03.2020 um 10:34 schrieb Justin Pryzby:

I think I would leave the "positive" variable names, and *add* negative forms
of the commandline options.  --no-foo and/or --foo=no


Yes, that would be nice. Unfortunately, the options are not interpreted 
by us, but by distutils. The way the options are currently defined in 
PyGreSQL they act as booleans that do not take arguments, i.e. you can 
set --foo, but not --foo=false. Unfortunately how the options are 
interpreted is not well documented (at least I find nothing), so I had 
to look into the Python source and found distutils uses getopt to parse 
the raw options. Therefore it is possible to require arguments by 
writing a "=" after the name of the argument in user_options, e.g.


('escaping-funcs=', None, "enable string escaping functions"),

When defined that way, we will be able to pass "--escaping-funcs=no" or 
"--escaping-funcs false" as an option. When 'escaping-funcs' is added to 
boolean_options, then the argument needs to be something like 0/false/no 
or 1/true/yes and will be converted to a Python bool.


Unfortunately, getopt does not allow default arguments. So it looks like 
we have to choose between:


1) Either two options --escaping-funcs and --no-escaping-funcs, both 
without arguments or

2) one option --escaping funcs with a mandatory boolean argument

In both cases, when we set self.escaping_funcs = None in 
initialize_options, we can implement the ternary on/off/default.


Not sure whether 1) or 2) is better, what do you think?

-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-25 Thread Justin Pryzby
On Wed, Mar 25, 2020 at 10:08:25AM +0100, Christoph Zwerschke wrote:
> 
> Am 25.03.2020 um 02:20 schrieb Justin Pryzby:
> > The old stuff can be removed eventually.  I like this:
> >
> >  if self.escaping_funcs and pg_version >= (9, 0):
> >  define_macros.append(('ESCAPING_FUNCS', None))
> > That allows a packager to disable a feature
> > if they want the abilityto run> against old libpq.
> 
> The problem is that these switches are by default set to true. The idea was
> that you set them to false on the command line if you don't want these
> features to be compiled. However, I think that never worked since you simply
> can't set these flags to false on the command line, you only can set them to
> true by specifying the names of the options (i.e. pass --escaping-funcs as
> option).
> 
> So we need to change that and instead use the negatives of these flags
> everywhere as options i.e. "no_escaping_funcs" in this case.

I think I would leave the "positive" variable names, and *add* negative forms
of the commandline options.  --no-foo and/or --foo=no

Also, I believe it used to be a best-practice for distribution packagers to
specify --with-foo --with-bar --with-baz even if those were the defaults (or if
they defaulted to true if libfoo/bar/baz were installed).  That avoids silently
building packages with reduced functionality if libfoo isn't found at compile
time.  So logic like this might be nice:

if self.enable_memsize and pg_version < (12, 0):
error('memsize not supported until pg12')

postgres vacuum options have a ternary system: on/off/default.  If you need
more than a line of logic, maybe you'd write:

if self.enable_memsize is True and pg_version < (12, 0):
error('memsize not supported until pg12')
else if self.enable_memsize == -1: # default/unset
self.enable_memsize = bool(pg_version >= (12, 0):)
...
if self.enable_memsize is True:
define_macros.append(('WITH_MEMSIZE', None))
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-25 Thread Christoph Zwerschke



Am 25.03.2020 um 02:20 schrieb Justin Pryzby:
> The old stuff can be removed eventually.  I like this:
>
>  if self.escaping_funcs and pg_version >= (9, 0):
>  define_macros.append(('ESCAPING_FUNCS', None))
> That allows a packager to disable a feature
> if they want the abilityto run> against old libpq.

The problem is that these switches are by default set to true. The idea 
was that you set them to false on the command line if you don't want 
these features to be compiled. However, I think that never worked since 
you simply can't set these flags to false on the command line, you only 
can set them to true by specifying the names of the options (i.e. pass 
--escaping-funcs as option).


So we need to change that and instead use the negatives of these flags 
everywhere as options i.e. "no_escaping_funcs" in this case. I usually 
avoid negative forms since "Can I not have my coffee with no sugar" 
sounds silly when I can say "Can I have coffee with sugar". But in the 
case where "sugar" is always the default, it's ok, since you only need 
to say "no sugar please" and never need to ask for sugar explicitly. (I 
hope this was not confusing :)


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-24 Thread Justin Pryzby
On Tue, Mar 24, 2020 at 09:10:18AM +0100, Christoph Zwerschke wrote:
> Maybe where we release binaries (currently only for Windows) we could ship
> them with a matching libql dll that will be installed with Pip alongside the
> PyGres dll?
I thinnk that would require the windows version of rpath which (depending on
who you ask) is discouraged.

> Or maybe link the pqlib statically into the PyGres dll in that
> case? This would make it even more convenient for Windows users since they
> don't need to install Postgres.

+1

Here, you talked about various compile-time switches.
https://github.com/PyGreSQL/PyGreSQL/issues/12

I guess it's good to continue supporting those, at least for newly-added
symbols that we *know* aren't in old releases.  What's out there seems to be
working for everyone.

The old stuff can be removed eventually.  I like this:

if self.escaping_funcs and pg_version >= (9, 0):
define_macros.append(('ESCAPING_FUNCS', None))

That allows a packager to disable a feature if they want the ability to run
against old libpq.

-- 
Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-24 Thread Christoph Zwerschke



Am 24.03.2020 um 05:46 schrieb Justin Pryzby:

This patch got stuck due to our limited understand of python's
dynamic loading of shared libraries.  I picked it up again ince I
have some downtime..
Thanks for working on this problem. Would be great if we could resolve 
it. Otherwise it always hinders us supporting the latest features.


> Since it's BIND_NOW, it means that any python program linked to
> pygres willsimply fail at startup in the unlikely even that it was
> compiled against libpq for PG12 but runs against an lib older

It's unlikely when you compile yourself, but Windows users normally 
don't do that since they have no compiler. So if we ship a version that 
was compiler against Pg12, it will not run for users with Pg11 installed 
on their machine. On the other hand, Windows DLL work a little bit 
differently anyway, maybe we can find a different solution there.


Maybe where we release binaries (currently only for Windows) we could 
ship them with a matching libql dll that will be installed with Pip 
alongside the PyGres dll? Or maybe link the pqlib statically into the 
PyGres dll in that case? This would make it even more convenient for 
Windows users since they don't need to install Postgres.


-- Christoph








___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2020-03-23 Thread Justin Pryzby
This patch got stuck due to our limited understand of python's dynamic loading
of shared libraries.  I picked it up again ince I have some downtime..

I think that way it's supposed to work, for an OS distribution, is that, at
compile time, whatever library is linked to, its SONAME is used, but also, its
*minor* version is captured by the distribution tools, and creates a package
dependency on library>=minorversion.  That means if you install a new version
of some tool, it might pull in a new version of a library, even if that's a
minor version.  Or it might pull in a totally new library package, since
distributions usually allow simultaneously installing libfoo1 (major=1) and
libfoo2 (major=2) to allow rolling transitions.  The debian tool that handles
that is dpkg-shlibdeps, and I know RHEL has something similar.

I don't see how that can work with pip, though..

It looks like python uses BIND_NOW when it dlopen's a library, like when pygres
does "from _pg import *".  Maybe because it *can't* work with pip.

I was able to make this work as I originally intended like:

$ PYTHONPATH=build/lib.linux-x86_64-3.5 python3 -c "import sys; 
sys.setdlopenflags(1); import pg; print(pg.DB('postgres').query('SELECT 
generate_series(1,)').memsize())" 
None

sys says:
|Among other things, this will enable a lazy resolving of symbols when 
importing a module, if called as sys.setdlopenflags(0).

But that didn't work for me.. Also, ctypes say:
|On posix systems, RTLD_NOW is always added, and is not configurable.

In any case, I don't think calling sys modules before importing _pg is a good
solution.  So I think the "solution" is to use a compile time check only, and
assume that it won't be run against an older version.  (And if need be, wait
until the new symbol is common enough that's a nonissue).

Since it's BIND_NOW, it means that any python program linked to pygres will
simply fail at startup in the unlikely even that it was compiled against libpq
for PG12 but runs against an lib older than 12.  It doesn't run for awhile and
then crash when the function is eventually called, which is bad.

On Sat, Oct 05, 2019 at 11:04:35AM -0500, Justin Pryzby wrote:
> On Sat, Oct 05, 2019 at 04:48:40PM +0200, Christoph Zwerschke wrote:
> > >Find attached minimal patch.
> 
> I thought it ought to have compile time check (for headers and link library
> version) and runtime check (for runtime lib version), but, now, even *with* my
> runtime library check, this happens if pygres is run against an earlier 
> version
> of libpq:
> 
> |$ PYTHONPATH=build/lib.linux-x86_64-2.7/ python2.7 -c "import pg; print 
> pg.DB('postgres').query('SELECT generate_series(1,)').memsize()"
> |Traceback (most recent call last):
> |  File "", line 1, in 
> |  File "pg.py", line 27, in 
> |from _pg import *
> |ImportError: /home/pryzbyj/src/pygres/build/lib.linux-x86_64-2.7/_pg.so: 
> undefined symbol: PQresultMemorySize
> 
> ..so maybe my runtime check is useless, or maybe libpq isn't doing proper
> library versioning?  I've forgotten whatever I once knew about this.
> 
> $ ldd build/lib.linux-x86_64-2.7/_pg.so |grep libpq
> libpq.so.5 => /usr/lib/x86_64-linux-gnu/libpq.so.5 
> (0x7fb3f652a000)

On Sat, Oct 05, 2019 at 11:47:40AM -0500, Justin Pryzby wrote:
> On Sat, Oct 05, 2019 at 06:37:36PM +0200, Christoph Zwerschke wrote:
> > >|$ PYTHONPATH=build/lib.linux-x86_64-2.7/ python2.7 -c "import pg; print 
> > >pg.DB('postgres').query('SELECT generate_series(1,)').memsize()"
> > >|Traceback (most recent call last):
> > >|  File "", line 1, in 
> > >|  File "pg.py", line 27, in 
> > >|from _pg import *
> > >|ImportError: /home/pryzbyj/src/pygres/build/lib.linux-x86_64-2.7/_pg.so: 
> > >undefined symbol: PQresultMemorySize
> > 
> > Are you sure you compiled that with the pgconfig.h of Postgres 12? setup.py
> > is using the includes specified by the pgconfig tool.
> 
> The intended behavior is to hit the runtime version check and then return 
> None.
> To check, I compiled against pg12 and then downgraded libpq to v10.
> 
> Built like:
> PATH=/usr/lib/postgresql/12/bin:$PATH ./setup.py build
> 
> If I hadn't, then it wouldn't have referenced PQresultMemorySize at all, 
> right ?

On Sat, Oct 05, 2019 at 01:53:23PM -0500, Justin Pryzby wrote:
> On Sat, Oct 05, 2019 at 07:47:50PM +0200, Christoph Zwerschke wrote:
> > Am 05.10.2019 um 18:47 schrieb Justin Pryzby:
> > > On Sat, Oct 05, 2019 at 06:37:36PM +0200, Christoph Zwerschke wrote:
> > >> Are you sure you compiled that with the pgconfig.h of Postgres 12?
> > >> setup.py is using the includes specified by the pgconfig tool.
> > > The intended behavior is to hit the runtime version check and then
> > > return None.
> > > To check, I compiled against pg12 and then downgraded libpq to v10.
> > > Built like: PATH=/usr/lib/postgresql/12/bin:$PATH ./setup.py build
> > > If I hadn't, then it wouldn't have referenced PQresultMemorySize at
> > > all, right ?
> > 
> > Ah, yes, you're 

Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-07 Thread Christoph Zwerschke

Am 06.10.2019 um 21:39 schrieb Justin Pryzby:
> That doesn't explain it :(
>
> Find attached t.c building t.so...

Thanks. At least we have ruled that out :/

Winter is coming and maybe we can find some rainy weekend to investigate 
deeper and learn a thing or two about the sacred science of building 
shared libraries...

___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-06 Thread Justin Pryzby
On Sun, Oct 06, 2019 at 05:57:38PM +0200, Christoph Zwerschke wrote:
> Am 06.10.2019 um 15:20 schrieb Justin Pryzby:
> > Remember, lazy binding is the default on my machine, and my patch
> > doesn't DWIW here..  So I don't think adding lazy link options
> > is going to help.  I think because of something python is doing (??)
> 
> Another difference is that in your example you're using libpq as shared lib
> directly, whereas with Python you create a shared lib that then uses libpq
> as a shared lib. Maybe it has something to do with that?

That doesn't explain it :(

Find attached t.c building t.so...

$ ldd t |sed 3q
linux-vdso.so.1 =>  (0x7ffd3fd32000)
t.so => not found
libpq.so.5 => /usr/lib/x86_64-linux-gnu/libpq.so.5 (0x7f27a8ba6000)
$ PGDATABASE=postgres LD_LIBRARY_PATH=. ./t 0
$ PGDATABASE=postgres LD_LIBRARY_PATH=. ./t 1
./t: symbol lookup error: ./t.so: undefined symbol: PQresultMemorySize

// sh -exc 'gcc -Wall -Wextra -O3 -g -I /usr/include/postgresql -o t.so -shared -fPIC -DSHARED=1 t.c && gcc -Wall -Wextra -O3 -g -o t -DSHARED=0 t.c t.so -lpq'
// $ PGDATABASE=postgres LD_LIBRARY_PATH=. ./t 1

#if	SHARED
#include 
#include 
#include 
void f(char **argv)
{
	PGconn *conn = PQconnectdb("");
	if (PQstatus(conn) != CONNECTION_OK)
		exit(1);
	PGresult *res = PQexec(conn, "SELECT generate_series(1,9)");
	if (argv[1][0] == '1')
		printf("%zd\n", PQresultMemorySize(res));
}

#else

void f(char **argv);
int main(int argc, char **argv)
{
	f(argv);
	return 0;
}
#endif // SHARED
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-06 Thread Christoph Zwerschke

Am 06.10.2019 um 15:20 schrieb Justin Pryzby:
> Remember, lazy binding is the default on my machine, and my patch
> doesn't DWIW here..  So I don't think adding lazy link options
> is going to help.  I think because of something python is doing (??)

Another difference is that in your example you're using libpq as shared 
lib directly, whereas with Python you create a shared lib that then uses 
libpq as a shared lib. Maybe it has something to do with that?


I kept the GitHub issue open as a reminder, and also created a Trac 
ticket referencing it.


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-06 Thread Justin Pryzby
On Sun, Oct 06, 2019 at 01:03:21PM +0200, Christoph Zwerschke wrote:
> Am 06.10.2019 um 01:15 schrieb Justin Pryzby:
> >On Sat, Oct 05, 2019 at 11:43:23PM +0200, Christoph Zwerschke wrote:
> >..but I don't think it's a solution for pygres ?  I tried it and still get a
> >symbol resolution error.  So, unless someone knows or finds better, it means
> >there's nothing stopping installing of pygres compiled against one library 
> >with
> >an earlier library, even though that combination might be broken.
> >
> >My #ifs and ifs don't help, and I suspect your setup.py stuff doesn't either 
> >(?)
> 
> When I tried building with setup.py, I noticed that Python links the shared
> lib in a separate step after the compilation. Options for this second step
> must be set in extra_link_args, not in extra_compile_args.
> I also noticed in the output that the shared lib is linked with the options
> -Wl,-Bsymbolic-functions and -Wl,-z,relro. Maybe this is what defeats the
> lazy binding?
> 
> Unfortunately. adding the options for lazy loading to extra_link_args,
> CFLAGS or LDFLAGS did not help, maybe because they are only appended (added)
> to the options above, and only the first option is effective?

Remember, lazy binding is the default on my machine, and my patch doesn't DWIW
here..  So I don't think adding lazy link options is going to help.  I think
because of something python is doing (??)

Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-06 Thread Christoph Zwerschke

Am 06.10.2019 um 01:15 schrieb Justin Pryzby:

On Sat, Oct 05, 2019 at 11:43:23PM +0200, Christoph Zwerschke wrote:
..but I don't think it's a solution for pygres ?  I tried it and still get a
symbol resolution error.  So, unless someone knows or finds better, it means
there's nothing stopping installing of pygres compiled against one library with
an earlier library, even though that combination might be broken.

My #ifs and ifs don't help, and I suspect your setup.py stuff doesn't either (?)


When I tried building with setup.py, I noticed that Python links the 
shared lib in a separate step after the compilation. Options for this 
second step must be set in extra_link_args, not in extra_compile_args.
I also noticed in the output that the shared lib is linked with the 
options -Wl,-Bsymbolic-functions and -Wl,-z,relro. Maybe this is what 
defeats the lazy binding?


Unfortunately. adding the options for lazy loading to extra_link_args, 
CFLAGS or LDFLAGS did not help, maybe because they are only appended 
(added) to the options above, and only the first option is effective?


Running out of time, need to investigate when I find some time again.

Or maybe someone with more knowledge of these things can explain what's 
going on here and how we can avoid the "undefined symbol" errors when 
using an older libpq version.


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Justin Pryzby
On Sat, Oct 05, 2019 at 11:43:23PM +0200, Christoph Zwerschke wrote:
> Am 05.10.2019 um 23:10 schrieb Christoph Zwerschke:
> >Just tried what you did with that t.c program, but strangely I get the
> >"undefined symbol" error when I downgrade libpq and run "./t 0", even when
> >LD_BIND_NOW is not defined. I am using Ubuntu instead of Debian, but that
> >shouldn't matter.
> 
> Ok, found the problem - I needed to explicitly add the "-Wl,-z,lazy" option
> when compiling t.c to make it use lazy binding. For some strange reason, it
> does not seem to be the default.
> 
> Maybe we need to add this to the extra_compile_args in the setup.py file as
> well?

It's intriguing that it's not the default on your machine..
(Maybe you can debug it some with nm -A |grep PQresultMemorySize or ldd or 
LD_DEBUG)

..but I don't think it's a solution for pygres ?  I tried it and still get a
symbol resolution error.  So, unless someone knows or finds better, it means
there's nothing stopping installing of pygres compiled against one library with
an earlier library, even though that combination might be broken.

My #ifs and ifs don't help, and I suspect your setup.py stuff doesn't either (?)

Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Christoph Zwerschke

Am 05.10.2019 um 23:33 schrieb Justin Pryzby:
> You probably realized that my email failed to show that I
> downgraded libpq between invocacations of "PGDATABASE=postgres ./t 1"

Yes, I understood what you were doing. But I could only reproduce it 
when adding the "-Wl,-z,lazy" option. Not sure why it's not the default 
on my machine.


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Christoph Zwerschke

Am 05.10.2019 um 23:10 schrieb Christoph Zwerschke:
Just tried what you did with that t.c program, but strangely I get the 
"undefined symbol" error when I downgrade libpq and run "./t 0", even 
when LD_BIND_NOW is not defined. I am using Ubuntu instead of Debian, 
but that shouldn't matter.


Ok, found the problem - I needed to explicitly add the "-Wl,-z,lazy" 
option when compiling t.c to make it use lazy binding. For some strange 
reason, it does not seem to be the default.


Maybe we need to add this to the extra_compile_args in the setup.py file 
as well?


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Justin Pryzby
On Sat, Oct 05, 2019 at 07:47:50PM +0200, Christoph Zwerschke wrote:
> 
> Am 05.10.2019 um 18:47 schrieb Justin Pryzby:
> > On Sat, Oct 05, 2019 at 06:37:36PM +0200, Christoph Zwerschke wrote:
> >> Are you sure you compiled that with the pgconfig.h of Postgres 12?
> >> setup.py is using the includes specified by the pgconfig tool.
> > The intended behavior is to hit the runtime version check and then
> > return None.
> > To check, I compiled against pg12 and then downgraded libpq to v10.
> > Built like: PATH=/usr/lib/postgresql/12/bin:$PATH ./setup.py build
> > If I hadn't, then it wouldn't have referenced PQresultMemorySize at
> > all, right ?
> 
> Ah, yes, you're right. The runtime checks are useless because you can't even
> load a shared library that doesn't support all the symbols that you are
> referencing somewhere.

In general, that's false, due to lazy binding (man ld.so: /LD_BIND_NOW/)
...but maybe true for python's c modules ??

$ sudo dpkg -i /var/cache/apt/archives/libpq{5,-dev}_12*deb
$ make CFLAGS="-Wall -Wextra -O3 -g -I /usr/include/postgresql" LDLIBS=-lpq t
$ PGDATABASE=postgres ./t 1
3459288
$ PGDATABASE=postgres ./t 1
./t: symbol lookup error: ./t: undefined symbol: PQresultMemorySize
$ PGDATABASE=postgres ./t 0 && echo OK
OK
$ LD_BIND_NOW=t PGDATABASE=postgres ./t 0 
./t: symbol lookup error: ./t: undefined symbol: PQresultMemorySize

Justin
// make CFLAGS="-Wall -Wextra -O3 -g -I /usr/include/postgresql" LDLIBS=-lpq t

#include 
#include 
#include 
int main(int argc, char **argv)
{
	PGconn *conn = PQconnectdb(""); // PGDATABASE dbname=postgres");
	if (PQstatus(conn) != CONNECTION_OK)
		exit(1);
	PGresult *res = PQexec(conn, "SELECT generate_series(1,9)");
	if (argv[1][0] == '1')
		printf("%zd\n", PQresultMemorySize(res));
	return 0;
}
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Christoph Zwerschke



Am 05.10.2019 um 18:47 schrieb Justin Pryzby:
> On Sat, Oct 05, 2019 at 06:37:36PM +0200, Christoph Zwerschke wrote:
>> Are you sure you compiled that with the pgconfig.h of Postgres 12?
>> setup.py is using the includes specified by the pgconfig tool.
> The intended behavior is to hit the runtime version check and then
> return None.
> To check, I compiled against pg12 and then downgraded libpq to v10.
> Built like: PATH=/usr/lib/postgresql/12/bin:$PATH ./setup.py build
> If I hadn't, then it wouldn't have referenced PQresultMemorySize at
> all, right ?

Ah, yes, you're right. The runtime checks are useless because you can't 
even load a shared library that doesn't support all the symbols that you 
are referencing somewhere.


That's actually the reason why I proposed supporting a "compatible 
version" option when building PyGreSQL, so that it's possible to create 
PyGreSQL binaries that can be used with older libpq versions.


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Christoph Zwerschke

Am 05.10.2019 um 18:04 schrieb Justin Pryzby:

On Sat, Oct 05, 2019 at 04:48:40PM +0200, Christoph Zwerschke wrote:

Find attached minimal patch.


Thank you, looks fine. I've already added docs and tests as well, but not
yet committed to trunk.


I didn't mean you had to stop and do that - I hammered it out while waiting for
pg_checksums to run :)


And I just had some spare time and was working on PyGres anyway :)


Good idea.  But I wonder whether it should be a property, which you suggested
before for types of queryResult columns (for which I sent a WIP patches July 19
and 20).


I thought about that. But this is a module level function and there are 
no module level properties in Python. Maybe we could use PEP 549 or 
PEP562, but these require Python 3.7. We could provide it as an 
attribute but that means we need to initialize it by making a call once 
when importing.



|$ PYTHONPATH=build/lib.linux-x86_64-2.7/ python2.7 -c "import pg; print 
pg.DB('postgres').query('SELECT generate_series(1,)').memsize()"
|Traceback (most recent call last):
|  File "", line 1, in 
|  File "pg.py", line 27, in 
|from _pg import *
|ImportError: /home/pryzbyj/src/pygres/build/lib.linux-x86_64-2.7/_pg.so: 
undefined symbol: PQresultMemorySize


Are you sure you compiled that with the pgconfig.h of Postgres 12? 
setup.py is using the includes specified by the pgconfig tool.


-- Christoph
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Justin Pryzby
On Sat, Oct 05, 2019 at 04:48:40PM +0200, Christoph Zwerschke wrote:
> >Find attached minimal patch.
> 
> Thank you, looks fine. I've already added docs and tests as well, but not
> yet committed to trunk.

I didn't mean you had to stop and do that - I hammered it out while waiting for
pg_checksums to run :)

Also, it occurred to me this "else" is unnecessary:

+#if PG_VERSION_NUM >= 12 /* Compile time version */
  
+if (PQlibVersion() >= 12) /* Runtime version */
  
+return PyLong_FromSize_t(PQresultMemorySize(self->result));
  
+else   
  

> In addition to query.memsize() I've also added get_pqlib_version() as a module
> level function.

Good idea.  But I wonder whether it should be a property, which you suggested
before for types of queryResult columns (for which I sent a WIP patches July 19
and 20).

> But I wonder if we should create a new minor version (5.2) instead of patch
> release (5.1.1) since it's new functionality?

It seems to me the usual procedure is to either issue a security release with
no other changes at all (not for py37, not for pg12, etc).  Or include the
security update with the next release.  FWIW, your schema-qualification commit
is already out there for anyone who wants it, and the CVE is from last year.

But, that's not an important patch; I don't think we'll use it at telsasoft
(preferring iterators); I think 5.2 should have more than a trivial new
feature.

> Another thing I'd also like to address is the overall handling of
> functionality that is optional or does only work with newer pqlib versions.
> Currently these are behind compiler switches which are set in setup.py, by
> default they are enabled if the pqlib version is new enough to support the
> respective functionality.

I think you're referring to:
$ grep -h '#if' *c |sort |uniq -c |sort -nr
... LARGE_OBJECTS DEFAULT_VARS ESCAPING_FUNCS DIRECT_ACCESS SSL_INFO NO_PQSOCKET

> Alternatively, the pqlib version could be checked directly using pg_config.h
> in the code instead of using the various switches,
> like you are doing here. I'd like to handle this more consistently through
> the code. But this would also warrant a new 5.2 version:
> see https://github.com/Cito/PyGreSQL/issues/12

I thought it ought to have compile time check (for headers and link library
version) and runtime check (for runtime lib version), but, now, even *with* my
runtime library check, this happens if pygres is run against an earlier version
of libpq:

|$ PYTHONPATH=build/lib.linux-x86_64-2.7/ python2.7 -c "import pg; print 
pg.DB('postgres').query('SELECT generate_series(1,)').memsize()"
|Traceback (most recent call last):
|  File "", line 1, in 
|  File "pg.py", line 27, in 
|from _pg import *
|ImportError: /home/pryzbyj/src/pygres/build/lib.linux-x86_64-2.7/_pg.so: 
undefined symbol: PQresultMemorySize

..so maybe my runtime check is useless, or maybe libpq isn't doing proper
library versioning?  I've forgotten whatever I once knew about this.

$ ldd build/lib.linux-x86_64-2.7/_pg.so |grep libpq
libpq.so.5 => /usr/lib/x86_64-linux-gnu/libpq.so.5 (0x7fb3f652a000)

Justin
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] [PATCH] PQresultMemorySize

2019-10-05 Thread Christoph Zwerschke

Am 05.10.2019 um 02:07 schrieb Justin Pryzby:

On Wed, May 15, 2019 at 08:44:49AM -0500, Justin Pryzby wrote:

Also, as of PG12 (unreleased), there'll be this new interface:
https://www.postgresql.org/docs/devel/release-12.html#id-1.3.7
|Add libpq function to report the memory size of the query result (Lars Kanis, 
Tom Lane)
|The function is PQresultMemorySize().

I'd propose to include that with the first release following PG12...although I
think you'd have to check PG_VERSION_NUM or similar, which I see isn't
currently being done.


Find attached minimal patch.


Thank you, looks fine. I've already added docs and tests as well, but 
not yet committed to trunk.


In addition to query.memsize() I've also added get_pqlib_version() as a 
module level function.


But I wonder if we should create a new minor version (5.2) instead of 
patch release (5.1.1) since it's new functionality?


Another thing I'd also like to address is the overall handling of 
functionality that is optional or does only work with newer pqlib 
versions. Currently these are behind compiler switches which are set in 
setup.py, by default they are enabled if the pqlib version is new enough 
to support the respective functionality.


Alternatively, the pqlib version could be checked directly using 
pg_config.h in the code instead of using the various switches,
like you are doing here. I'd like to handle this more consistently 
through the code. But this would also warrant a new 5.2 version:

see https://github.com/Cito/PyGreSQL/issues/12

-- Christoph

___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


[PyGreSQL] [PATCH] PQresultMemorySize

2019-10-04 Thread Justin Pryzby
On Wed, May 15, 2019 at 08:44:49AM -0500, Justin Pryzby wrote:
> Also, as of PG12 (unreleased), there'll be this new interface:
> https://www.postgresql.org/docs/devel/release-12.html#id-1.3.7
> |Add libpq function to report the memory size of the query result (Lars 
> Kanis, Tom Lane)
> |The function is PQresultMemorySize(). 
> 
> I'd propose to include that with the first release following PG12...although I
> think you'd have to check PG_VERSION_NUM or similar, which I see isn't
> currently being done.

Find attached minimal patch.

$ PYTHONPATH=build/lib.linux-x86_64-2.7/ python2.7 -c "import pg; print 
pg.DB('postgres').query('SELECT generate_series(1,)').memsize()"
372952
Index: pgmodule.c
===
--- pgmodule.c	(revision 1019)
+++ pgmodule.c	(working copy)
@@ -17,6 +17,7 @@
 
 #include 
 #include 
+#include 
 
 /* The type definitions from  */
 #include "pgtypes.h"
 
Index: pgquery.c
===
--- pgquery.c	(revision 1019)
+++ pgquery.c	(working copy)
@@ -11,6 +11,20 @@
  *
  */
 
+static char query_memsize__doc__[] =
+"memsize() -- return number of bytes allocated by query";
+static PyObject *
+query_memsize(queryObject *self)
+{
+#if PG_VERSION_NUM >= 12 /* Compile time version */
+if (PQlibVersion() >= 12) /* Runtime version */
+return PyLong_FromSize_t(PQresultMemorySize(self->result));
+else
+#endif
+Py_INCREF(Py_None);
+return Py_None;
+}
+
 /* Deallocate the query object. */
 static void
 query_dealloc(queryObject *self)
@@ -707,13 +788,21 @@
 METH_VARARGS, query_fieldnum__doc__},
 {"listfields", (PyCFunction) query_listfields,
 METH_NOARGS, query_listfields__doc__},
 {"ntuples", (PyCFunction) query_ntuples,
 METH_NOARGS, query_ntuples__doc__},
+{"memsize", (PyCFunction) query_memsize,
+METH_NOARGS, query_memsize__doc__},
 {NULL, NULL}
 };
 
 static char query__doc__[] = "PyGreSQL query object";
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql