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

From Dmitriy Igrishin
Subject Re: [HACKERS] Frontend/backend protocol improvements proposal (request).
Date
Msg-id CAAfz9KMeKniU2f7H41g9JKfjKm3hq3NaSqzMruAwUZJzz9izCA@mail.gmail.com
Whole thread Raw
In response to Re: [HACKERS] Frontend/backend protocol improvements proposal (request).  (Albe Laurenz <laurenz.albe@wien.gv.at>)
List pgsql-general



2013/6/28 Albe Laurenz <laurenz.albe@wien.gv.at>
Dmitriy Igrishin wrote:
>> 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.
>
> More precisely, there can be only one uniquely named prepared statement (named
> or unnamed) per session.
> Could you provide a signature of parseUnnamed and executeUnnamed please?
> I don't clearly understand this approach.

I'm just brainstorming.
I'm thinking of something like
void Connection::prepareUnnamed(const char *query,
                         int nParams,
                         const Oid *paramTypes);
and
Result Connection::executeUnnamed(int nParams,
                         const char * const *paramValues,
                         const int *paramLengths,
                         const int *paramFormats,
                         int resultFormat);

But I'm not saying that this is the perfect solution.
I see. It's more like C-styled design, but not C++.

>> 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.
>
> The mentioned burden is already handled by backend which throws
> duplicate_prepared_statement (42P05) error.

I mean the problem that you create a prepared statement,
then issue "DEALLOCATE stmt_name" create a new prepared statement
with the same name and then use the first prepared statement.
I see. But I see no problem to invalidate localy allocated descriptors
of the remote prepared statements 

>>> Prepared_statement* pst1 = connection->describe("name");
>>> Prepared_statement* pst2 = connection->describe("name"); // pst2 points to the same remote
>>> object
>>
>> 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?
>
> Well, then the C and C++ languages are bad designed too, because they
> allow to have as many pointers to the same as the user like (needs) :-)

That's a different thing, because all these pointers contain the same
value.  So if pst1 and pst2 represent the same object, I'd like
pst1 == pst2 to be true.
IOW, you want to map localy allocated object to the remote one.
Or course, it is possible. But I dislike approach, since:
  a) objects pointed by pst* should be owned by the Connection instance;
  b) these objects may have its own state depending on the application
     context (e.g., different valuess binded, result format settings etc etc.)
     but it will be impossible due to a).
BTW, according to 18.6.3.1 of "The C++ Programming Language" by Stroustrup,
"The default meaning of < and == for pointers are rarely useful as comparison criteria
for the objects pointed to." So, I believe that you means that you'd like
*pst1 == *pst2. And yes, I'll agree with it.

> Really, I don't see bad design here. Describing prepared statement
> multiple times will results in allocating several independent descriptors.

... but for the same prepared statement.

> (As with, for example, performing two SELECTs will result in allocating
> several independent results by libpq.)

But those would be two different statement to PostgreSQL, even if the
query strings are identical.

Mind you, I'm not saying that I am the person that decides what is
good taste and what not, I'm just sharing my sentiments.
Don't worry, I'm mature enough to understand this :-) And thank you
for you suggestions!

>> 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.
>
> Why this error should be ignored? I believe that this should be decided by the user.
> As a library author I don't know (and cannot know) how to react on such errors
> in the end applications.

Again, I would say that that is a matter of taste.
I just cannot think of a case where this would be important.
Maybe, but I'm firmly belive, that errors, provoked by the user, should
not be ignored at all. This is a one of design principles of my library.

>>> 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.
>
> Perhaps, but, again, I don't know how the user will prefer to react. So, I prefer just
> to throw and allow the user to decide.

Agreed, it's a matter of taste.

Yours,
Laurenz Albe


--
// Dmitriy.

pgsql-general by date:

Previous
From: Alban Hertroys
Date:
Subject: Re: passing text value with single quote to stored procedure
Next
From: "James B. Byrne"
Date:
Subject: Re: Build RPM from Postgres Source