2016-01-26 8:22 GMT+01:00 Pavel Stehule <pavel.steh...@gmail.com>: > > > 2016-01-26 7:31 GMT+01:00 Catalin Iacob <iacobcata...@gmail.com>: > >> On 1/21/16, Pavel Stehule <pavel.steh...@gmail.com> wrote: >> > 2016-01-14 17:16 GMT+01:00 Catalin Iacob <iacobcata...@gmail.com>: >> >> Consider this call chain: SQL code 1 -> PL/Python code 1 -> SPI (via >> >> plpy.execute) -> SQL code 2 -> PL/Python code 2 >> >> >> >> If I'm writing PL/Python code 1 and I want to raise an error toward >> >> SQL code 1 I use raise plpy.Error. plpy.SPIError is what I get if I >> >> call into SQL code 2 and that has an error. That error could indeed >> >> come from a plpy.Error thrown by PL/Python code 2 or it could come >> >> from a SQL syntax error or whatever. But the symmetry holds: >> >> plpy.Error is what you raise to stop the query and return errors to >> >> your SQL caller and plpy.SPIError is what you get back if you use SPI >> >> to execute some other piece of SQL which has an error. I *think* (I'm >> >> an internals newbie though so I could be wrong) that SQL code 1 >> >> doesn't call into PL/Python code 1 via SPI so why would the latter use >> >> something called SPIError to inform the former about an error? >> >> >> > >> > It is not correct - outside PLPython you got a Error (PostgreSQL error >> has >> > not any classes), and isn't important the raising class (Error or >> > SPIError). Inside PL/Python you will got SPIError or successors (based >> on >> > SQLcode). >> >> What exactly is not correct? Indeed, *outside* PLPython you don't get >> a Python exception because Postgres isn't Python, you get Postgres' >> way of representing an exception (error code, message, hint and so on >> that might go to the client or not etc.). But that's normal, it's just >> the impedance mismatch between the fact that you embed Python with its >> rules into Postgres with its other rules. It's normal that the "host" >> (Postgres) wins in the end and uses its mechanism to report errors. >> The "guest" (PLPython) is there only to give mechanisms to activate >> the "host". >> >> But *inside* PLPython what I wrote is true, see this example for what I >> mean: >> >> CREATE FUNCTION test() >> RETURNS int >> AS $$ >> def a_func(): >> raise plpy.Error('an error') >> >> try: >> a_func() >> except plpy.Error as exc: >> plpy.info('have exc {} of type {}'.format(exc, type(exc))) >> plpy.info('have spidata {}'.format(hasattr(exc, 'spidata'))) >> $$ LANGUAGE plpython3u; >> >> Running this produces: >> >> DROP FUNCTION >> CREATE FUNCTION >> psql:plpy_demo:16: INFO: have exc an error of type <class 'plpy.Error'> >> psql:plpy_demo:16: INFO: have spidata False >> >> > Currently If I raise plpy.Error, then it is immediately trasformed to >> > PostgreSQL, and and then to SPIError and successors. >> >> Depends how you define immediately. I would say it's really not >> immediately, it's only at the Postgres boundary. Imagine in the >> example above that a_func could call lots of other Python code and >> somewhere deep down raise Error would be used. Within that whole >> execution the error stays Error and can be caught as such, it will >> have nothing to do with SPIError. >> >> But in my opinion this discussion shouldn't really even be about >> catching these things, most of the times you won't catch them and >> instead you'll let them go to Postgres. The discussion should be >> whether raise plpy.Error(...), plpy.raise_error, plpy.raise_info(,,,) >> etc. all with keyword argument support are a good PLPython interface >> to Postgres' ereport. I think they are. >> >> On a different note, I've explained what I think but I might be wrong >> and don't want to stall the patch just because I don't agree with the >> approach it takes. >> >> The waiting for author status is ok since, as far as I can see, Pavel >> also agrees that at least some of the issues raised in >> >> http://www.postgresql.org/message-id/CAHg_5grU=LVRbZDhfCiiYc9PhS=1X5f=gd44-3jcul-qaor...@mail.gmail.com >> need to be fixed. >> >> Would it help maybe to remove myself as reviewer in the CF? Maybe that >> makes somebody else pick it up and move it further. >> > please, wait. We can finish the part, where is a agreement. And although it is not final solution from Python perspective - I hope, so it can be really useful for PLPython user - there will be one way how to raise rich exception without ugly workaround
Regards Pavel > >> I could also code the version I'm describing but that design would be >> contrary to what Jim and Pavel lean towards now. It could help to >> compare approaches side by side but I don't like the idea of dueling >> patches. >> > > I would to reduce this patch and don't try to touch on buildin exceptions. > I hope, so there isn't any disagreement? > > I though about it lot of, and I see a the core of problems in orthogonal > constructed exceptions in Python and Postgres. We working with statements > elog, ereport, RAISE EXCEPTION - and these statements are much more like > templates - can generate any possible exception. Python is based on working > with instances of predefined exceptions. And it is core of problem. > Template like class cannot be ancestor of instance oriented classes. This > is task for somebody who knows well OOP and meta OOP in Python - total > different chapter, different patch. > > > Regards > > Pavel > > >