Thread: libpq++
I recently got the latest source from cvs. I think there's a bug in pgtransdb.cc. The pgCommitted flag will never be true after the implicit BeginTransaction called by creating a PgCursor. I ran testlibpq3.cc with logging enabled -- sure enough when using a cursor ABORT is always executed in PgTransaction destructor. When fetching this has no effect, but still. Am I missing something? Does one need to somehow explicitly call EndTransaction? If so, how? That's a protected member, and nothing in PgCursor seems to call it. Also, PgCursor is the only module I can see that has std:: namespace dependency. Why? Thanks for your time Dave Joyner _________________________________________________________ Do You Yahoo!? Get your free @yahoo.com address at http://mail.yahoo.com
Okay, I see your point, especially your comments on the object hierarchy. Because here's the problem (someone must have seen this already): PgCursor c("host=localhost", "foo"); c.Declare("select * from foo where something=somethingelse"); c.Fetch(); for (int i = 0; i < c.Tuples(); i++) { if (something is true) { c.ExecCommandOk("update bar set something=something where something=somethingelse") ) } } c.Close();// just rolled back all those updates, but have no idea why! Thanks Dave ... ----- Original Message ----- From: "Tom Lane" <tgl@sss.pgh.pa.us> To: "David Joyner" <d4ljoyn@yahoo.com> Cc: <pgsql-interfaces@postgresql.org> Sent: Monday, January 14, 2002 5:50 PM Subject: Re: [INTERFACES] libpq++ > "David Joyner" <d4ljoyn@yahoo.com> writes: > > I recently got the latest source from cvs. I think there's a bug in > > pgtransdb.cc. The pgCommitted flag will never be true after the implicit > > BeginTransaction called by creating a PgCursor. > > This code is pretty grotty, but that particular issue I don't think is a > problem. AFAICS, since a PgTransaction object opens its own database > connection (yipes!), the only thing ever done in a PgCursor's > transaction will be to create and read from the cursor. So whether we > commit or abort hardly matters. > > The real bletcherousness is the overhead of establishing a separate > connection for each transaction. > > Fixing this would probably entail a wholesale redesign of PgCursor, > PgTransaction, and friends, and would break any applications that are > using them successfully :-( > > There is someone working on a brand-new C++ interface library which > perhaps will avoid all the mistakes that were made in libpq++. You > might want to pitch in with that work. Check the recent archives > for (I think) libpqxx. > > regards, tom lane _________________________________________________________ Do You Yahoo!? Get your free @yahoo.com address at http://mail.yahoo.com
"David Joyner" <d4ljoyn@yahoo.com> writes: > I recently got the latest source from cvs. I think there's a bug in > pgtransdb.cc. The pgCommitted flag will never be true after the implicit > BeginTransaction called by creating a PgCursor. This code is pretty grotty, but that particular issue I don't think is a problem. AFAICS, since a PgTransaction object opens its own database connection (yipes!), the only thing ever done in a PgCursor's transaction will be to create and read from the cursor. So whether we commit or abort hardly matters. The real bletcherousness is the overhead of establishing a separate connection for each transaction. Fixing this would probably entail a wholesale redesign of PgCursor, PgTransaction, and friends, and would break any applications that are using them successfully :-( There is someone working on a brand-new C++ interface library which perhaps will avoid all the mistakes that were made in libpq++. You might want to pitch in with that work. Check the recent archives for (I think) libpqxx. regards, tom lane
"David Joyner" <d4ljoyn@yahoo.com> writes: > Okay, I see your point, especially your comments on the object hierarchy. > Because here's the problem (someone must have seen this already): > PgCursor c("host=localhost", "foo"); > c.Declare("select * from foo where something=somethingelse"); > c.Fetch(); > for (int i = 0; i < c.Tuples(); i++) > { > if (something is true) > { > c.ExecCommandOk("update bar set something=something where > something=somethingelse") ) > } > } > c.Close(); > // just rolled back all those updates, but have no idea why! I'd argue that c.ExecCommandOk() is a bogus operation for a PgCursor object to be providing... a cursor is not something that should be able to execute SQL queries unrelated to the cursor. It would make more sense to me for PgCursor to have open/fetch/close operations and not much else, and for it to be created with a reference to an already-open Connection object that provides the conduit for the cursor commands. To make this work, probably the Connection object would have to keep track of whether the backend is inside a transaction block, and not allow the transaction to be closed as long as there were live PgCursors attached to it. regards, tom lane
I agree with you. I guess the person that wrote it is not here to defend themselves, so I'll just work around. Thanks Dave ----- Original Message ----- From: "Tom Lane" <tgl@sss.pgh.pa.us> To: "David Joyner" <d4ljoyn@yahoo.com> Cc: <pgsql-interfaces@postgresql.org> Sent: Monday, January 14, 2002 6:32 PM Subject: Re: [INTERFACES] libpq++ > "David Joyner" <d4ljoyn@yahoo.com> writes: > > Okay, I see your point, especially your comments on the object hierarchy. > > Because here's the problem (someone must have seen this already): > > > PgCursor c("host=localhost", "foo"); > > c.Declare("select * from foo where something=somethingelse"); > > c.Fetch(); > > for (int i = 0; i < c.Tuples(); i++) > > { > > if (something is true) > > { > > c.ExecCommandOk("update bar set something=something where > > something=somethingelse") ) > > } > > } > > c.Close(); > > // just rolled back all those updates, but have no idea why! > > I'd argue that c.ExecCommandOk() is a bogus operation for a PgCursor > object to be providing... a cursor is not something that should be > able to execute SQL queries unrelated to the cursor. > > It would make more sense to me for PgCursor to have open/fetch/close > operations and not much else, and for it to be created with a reference > to an already-open Connection object that provides the conduit for the > cursor commands. To make this work, probably the Connection object > would have to keep track of whether the backend is inside a transaction > block, and not allow the transaction to be closed as long as there were > live PgCursors attached to it. > > regards, tom lane > > ---------------------------(end of broadcast)--------------------------- > TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org _________________________________________________________ Do You Yahoo!? Get your free @yahoo.com address at http://mail.yahoo.com
On Mon, Jan 14, 2002 at 07:16:41PM -0500, David Joyner wrote: > I agree with you. I guess the person that wrote it is not here to defend > themselves, so I'll just work around. Alternatively, you may want to look at libpqxx. Written as a replacement for libpq++, it has a more modern interface and--knock on wood--addresses each of the issues discussed here. You lose the "convenience" (and the inflexibility) of having transactions, connections, and query results all reside in a single object, and gain the convenience of using exception handling instead of manual result checking. You can find it at http://members.ams.chello.nl/j.vermeulen31/proj-libpqxx.html I hope someday this could be included in the main PostgreSQL source tree. Jeroen