Index: dbdimp.c
===================================================================
--- dbdimp.c	(revision 14529)
+++ 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 14529)
+++ 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 14529)
+++ 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
Index: t/03smethod.t
===================================================================
--- t/03smethod.t	(revision 14529)
+++ t/03smethod.t	(working copy)
@@ -9,6 +9,7 @@
 use 5.006;
 use strict;
 use warnings;
+use POSIX qw(:signal_h);
 use Test::More;
 use DBI ':sql_types';
 use lib 't','.';
@@ -20,7 +21,7 @@
 if (! $dbh) {
 	plan skip_all => 'Connection to database failed, cannot continue testing';
 }
-plan tests => 96;
+plan tests => 97;
 
 isnt ($dbh, undef, 'Connect to database for statement handle method testing');
 
@@ -652,6 +653,36 @@
 $sth->fetchall_arrayref();
 is ($sth->{pg_current_row}, 0, $t);
 
+#
+# Test of the statement handle method "cancel"
+#
+
+$dbh->do('INSERT INTO dbd_pg_test (id) VALUES (?)',undef,1);
+$dbh->commit;
+$dbh->do('SELECT * FROM dbd_pg_test WHERE id = ? FOR UPDATE',undef,1);
+
+my $dbh2 = $dbh->clone;
+$dbh2->do('SET search_path TO ' . $dbh->selectrow_array('SHOW search_path'));
+
+my $oldaction;
+eval {
+	# This statement will block indefinitely becaue of the 'FOR UPDATE' clause,
+	# so we set up an alarm to cancel it after 2 seconds.
+	my $sth = $dbh2->prepare('SELECT * FROM dbd_pg_test WHERE id = ? FOR UPDATE');
+	$sth->{RaiseError} = 1;
+
+	my $action = POSIX::SigAction->new(sub {$sth->cancel},POSIX::SigSet->new(SIGALRM));
+	$oldaction = POSIX::SigAction->new;
+	POSIX::sigaction(SIGALRM,$action,$oldaction);
+
+	alarm(2); # seconds before alarm
+	$sth->execute(1);
+	alarm(0); # cancel alarm (if execute didn't block)
+};
+POSIX::sigaction(SIGALRM,$oldaction); # restore original signal handler
+like ($@,qr/canceling statement due to user request/,'cancel');
+$dbh2->disconnect();
+
 cleanup_database($dbh,'test');
 $dbh->rollback();
 $dbh->disconnect();
