Re: [HACKERS] Frontend/backend protocol improvements proposal (request). - Mailing list pgsql-general

From Albe Laurenz
Subject Re: [HACKERS] Frontend/backend protocol improvements proposal (request).
Date
Msg-id A737B7A37273E048B164557ADEF4A58B17BB6BF1@ntex2010a.host.magwien.gv.at
Whole thread Raw
In response to Re: [HACKERS] Frontend/backend protocol improvements proposal (request).  (Dmitriy Igrishin <dmitigr@gmail.com>)
Responses Re: [HACKERS] Frontend/backend protocol improvements proposal (request).  (Dmitriy Igrishin <dmitigr@gmail.com>)
List pgsql-general
Dmitriy Igrishin wrote:
>> I understand the problem now.
>> I pondered a bit over your design, and I came up with a different
>> idea how to represent prepared statements in a C++ library.

>> First, a prepared statement is identified by its name.
>> To make the relationship between a PreparedStatement object
>> and the PostgreSQL prepared statement unique, I suggest that
>> the prepared statement name should not be exposed to the
>> library user.  It should be a private property that is
>> set in the initializer in a unique fashion (for example, it
>> could be a string representation of the memory address
>> of the object).
>> That way, there can never be a name collision.  That should take
>> care of the problem.
> 
> 
> In fact something like was implemented in very early versions of my
> library. There are some reasons why I've redesigned the library:
> 
> 1) If the user does not specify the name of the prepared statement (or
> specify it as "") it is considered as unnamed prepared statement -- a one of
> the important concepts of the frontend/backend protocol, which is a base of
> my current design.
> The unnamed prepared statements are very useful since they are deallocated
> authomatically when the backend receives the next Parse message with
> empty name.

If you want unnamed prepared statements in your library, I would
use a different class for them since they behave quite differently.
That would also make this concern go away.

Since there can be only one unnamed prepared statement per
session, there should be only one such object per connection.
It should not get deallocated; maybe it could be private to the
connection, which only offers a "parseUnnamed" and "executeUnnamed"
mathod.

> 2) Meaningful names of the named prepared statements (as any other database
> objects) may be useful while debugging the application. Imagine the memory
> addresses (or any other surrogate names) in the Postgres logs...

That wouldn't worry me, but that's a matter of taste.

> Hence, the name() method should be public and name().empty() means
> unnamed prepared statement.

You could offer a getter for the name if anybody needs it for debugging.

If you really want your users to be able to set prepared statement
names, you'd have to warn them to be careful to avoid the
problem of name collision -- you'd handle the burden to them.
That's of course also a possible way, but I thought you wanted
to avoid that.

>> I also wouldn't provide a deallocate() method.  A deallocated
>> prepared statement is useless.  I think that it would be more
>> logical to put that into the destructor method.
>> If somebody wants to get rid of the prepared statement
>> ahead of time, they can destroy the object.
> 
> 
> I've also considered this approach and there are some reasons why I don't
> implemented the prepared statement class this way:
> 
> 1) There are Describe message in the protocol. Thus, any prepared statement
> can be also described this way:
>   Prepared_statement* pst1 = connection->describe("name");
>   Prepared_statement* pst2 = connection->describe("name"); // pst2 points to the same remote object
> Think about the pst as a pointer to the remote object (prepared statement).
> Since each statement can be described multiple times, the deleting one of them
> should not result in deallocating the prepared statement by the backend.

That seems like bad design to me.
I wouldn't allow different objects pointing to the same prepared
statement.  What is the benefit?
Shouldn't the model represent reality?

> 2) The best way to inform the user about errors in the modern C++ are exceptions.
> The dellocate operation (as any other query to the database) can be result in
> throwing some exception. But descructors should not throw. (If you are familiar with
> C++ well you should know about the gotchas when destructors throw.)
> So, there are deallocate() method which seems to me ok.

Of course an error during DEALLOCATE should be ignored in that case.
It's hard to conceive of a case where deallocation fails, but the
connection is fine.  And if the connection is closed, the statement
will be deallocated anyway.

> Btw, by the reason 2) there are no any transaction RAII classes as in some other libraries,
> because the ROLLBACK command should be executed in the destructor and may throw.

I tend to believe that such errors could also be ignored.
If ROLLBACK (or anything else) throws an error, the transaction will
get rolled back anyway.

Yours,
Laurenz Albe

pgsql-general by date:

Previous
From: Adarsh Sharma
Date:
Subject: Re: Concatenate table name in Pl/Pgsql
Next
From: Albe Laurenz
Date:
Subject: Re: utf8 errors