DBD::Pg Implementation for cancel()?

"Eric Simon" <[email protected]> Mon, 18 Oct 2010 22:53:22 -0500
Newsgroups gmane.comp.lang.perl.modules.dbi.general,gmane.comp.db.postgresql.dbdpg
Message-ID <B6688AE83EF44F01B7F00F045573A1F5@Masterchief>
Doh!  It is attached now.

-- 
Eric Simon
The IQ Group, Inc.


-----Original Message-----
From: Eric Simon [mailto:[email protected]] 
Sent: Monday, October 18, 2010 10:52 PM
To: 'Greg Sabino Mullane'; '[email protected]'; '[email protected]'
Subject: DBD::Pg Implementation for cancel()?

Hi Greg/all,

I've implemented cancel() for DBD::Pg and it works just like the one for
DBD::Oracle.  I've attached a patch in case you'd like to roll it in to your
next version.

-- 
Eric Simon
The IQ Group, Inc.


-----Original Message-----
From: Greg Sabino Mullane [mailto:[email protected]] 
Sent: Thursday, August 05, 2010 4:24 PM
To: [email protected]
Subject: RE: DBD::Pg Implementation for cancel()?


-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160

From: "Eric Simon" <[email protected]>
To: <[email protected]>
Subject: RE: DBD::Pg Implementation for cancel()?
Date: 6:19 PM on Wednesday, August 04, 2010
X-Maillaunder-Av-Scan: YES:40743a065537e4cb1b81cbd0584176e7
X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on
incoming.maillaunder.com
X-Spam-Level: 
X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_HI,
RDNS_NONE,SPF_PASS,TW_PG autolearn=ham version=3.2.5
X-Spam-PDF-Info: pdf=_PDFCOUNT_, pdfimg=_PDFIMGCOUNT_, ver=_PDFVERSION_,
name=_PDFNAME_
X-Mailer: Microsoft Office Outlook 11
X-Mimeole: Produced By Microsoft MimeOLE V6.1.7600.16543
X-Old-Spam-Status: No, score=-2.5 required=3.3
tests=ALL_TRUSTED,AWL,BAYES_00, DNS_FROM_RFC_BOGUSMX autolearn=no
version=3.2.5

...
> confusing.  I meant to say that we wouldn't need to use pg_async if
> if $sth->cancel() was implemented.  To be more specific, we are doing
> something very close to what the DBI docs show in their "Signal Handling
> and Canceling Operations" section.  Here is our abridged code that works
> on DBD::Oracle:
...

Ah, okay, now it makes sense with the alarm. I will look into if that 
will work with DBD::Pg but it may be a while, I'm very backed up at 
the moment. (Here's your chance, all you quiet potential dbdpg hackers 
on this list! :)

> I'll see what I can do about narrowing down the destabilizing affect 
> that pg_async had in our test suite, although narrowing that down will 
> take quite some time (because I don't want to just shove a ton of code at
you).

Yeah, small reproducible test cases are worth the wait. Send what you can, 
when you can. Better still, open a bug at rt.cpan.org if you think it's 
a problem on our end. Thanks.

- -- 
Greg Sabino Mullane [email protected]
End Point Corporation http://www.endpoint.com/
PGP Key: 0x14964AC8 201008051721
http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8
-----BEGIN PGP SIGNATURE-----

iEYEAREDAAYFAkxbK8cACgkQvJuQZxSWSsjhlQCeMc0RJMarcQRIEcdGJl1fjEyJ
9vkAoJ0Jm1xL55qJoegi3hFM75o/4Cnd
=O9aR
-----END PGP SIGNATURE-----
dbd-pg-patch-for-cancel.patch (application/octet-stream, 2.2 KB)
Index: dbdimp.c
===================================================================
--- dbdimp.c	(revision 14500)
+++ dbdimp.c	(working copy)
@@ -4909,7 +4909,40 @@
 } /* end of handle_old_async */
 
 
+/* ================================================================== */
+/* Attempt to cancel a synchronous query
+   Returns true if the cancel succeeded, and false if it did not */
+int dbd_st_cancel(SV *sth, imp_sth_t *imp_sth)
+{
+	dTHX;
+	D_imp_dbh_from_sth;
+	PGcancel *cancel;
+	char errbuf[256];
 
+	if (TSTART) TRC(DBILOGFP, "%sBegin dbd_st_cancel\n", THEADER);
+
+	/* Get the cancel structure */
+	TRACE_PQGETCANCEL;
+	cancel = PQgetCancel(imp_dbh->conn);
+
+	/* This almost always works. If not, free our structure and complain loudly */
+	TRACE_PQGETCANCEL;
+	if (!PQcancel(cancel, errbuf, sizeof(errbuf))) {
+		TRACE_PQFREECANCEL;
+		PQfreeCancel(cancel);
+		if (TRACEWARN) TRC(DBILOGFP, "%sPQcancel failed: %s\n", THEADER, errbuf);
+		pg_error(aTHX_ sth, PGRES_FATAL_ERROR, "PQcancel failed");
+		if (TEND) TRC(DBILOGFP, "%sEnd dbd_st_cancel (error: cancel failed)\n", THEADER);
+		return DBDPG_FALSE;
+	}
+	TRACE_PQFREECANCEL;
+	PQfreeCancel(cancel);
+
+	if (TEND) TRC(DBILOGFP, "%sEnd dbd_st_cancel\n", THEADER);
+	return DBDPG_TRUE;
+
+} /* end of dbd_st_cancel */
+
 /*
 Some information to keep you sane:
 typedef enum
Index: dbdimp.h
===================================================================
--- dbdimp.h	(revision 14500)
+++ dbdimp.h	(working copy)
@@ -166,9 +166,12 @@
 #define dbd_st_rows pg_st_rows
 int dbd_st_rows (SV * sth, imp_sth_t * imp_sth);
 
-#define dbd_st_finish  pg_st_finidh
+#define dbd_st_finish  pg_st_finish
 int dbd_st_finish (SV * sth, imp_sth_t * imp_sth);
 
+#define dbd_st_cancel pg_st_cancel
+int dbd_st_cancel (SV * sth, imp_sth_t * imp_sth);
+
 #define dbd_st_destroy  pg_st_destroy
 void dbd_st_destroy (SV * sth, imp_sth_t * imp_sth);
 
Index: Pg.xs
===================================================================
--- Pg.xs	(revision 14500)
+++ Pg.xs	(working copy)
@@ -796,6 +796,13 @@
 	D_imp_sth(sth);
 	ST(0) = pg_db_cancel_sth(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no;
 
+void
+cancel(sth)
+	SV *sth
+	CODE:
+	D_imp_sth(sth);
+	ST(0) = dbd_st_cancel(sth, imp_sth) ? &PL_sv_yes : &PL_sv_no;
+
 #if PGLIBVERSION >= 80000
 
 void