[svn:DBD-Pg] r14471 - in DBD-Pg/trunk: . t

[email protected]
Newsgroups gmane.comp.db.postgresql.dbdpg.cvs
Message-ID <[email protected]>
Author: machack666
Date: Fri Oct  8 22:33:58 2010
New Revision: 14471

Modified:
   DBD-Pg/trunk/quote.c
   DBD-Pg/trunk/t/03dbmethod.t
   DBD-Pg/trunk/t/06bytea.t

Log:
Support dequoting PostgreSQL 9.0 "hex" BYTEA output format

In PostgreSQL 9.0, the default BYTEA output format has changed from
octal escapes for non-printable-ascii characters to encoding the whole
value in hex (with a leading "\x" to distinguish the two).

This also removes papering-over of the lack of dequoting from
t/03dbmethod.t and extends t/06bytea.t to cover both output formats.

Modified: DBD-Pg/trunk/quote.c
==============================================================================
--- DBD-Pg/trunk/quote.c	(original)
+++ DBD-Pg/trunk/quote.c	Fri Oct  8 22:33:58 2010
@@ -442,7 +442,7 @@
 
 
 
-void dequote_bytea(char *string, STRLEN *retlen, int estring)
+static void _dequote_bytea_escape(char *string, STRLEN *retlen, int estring)
 {
 	dTHX;
 	char *result;
@@ -482,6 +482,58 @@
 	return;
 }
 
+static int _decode_hex_digit(char digit)
+{
+	dTHX;
+	if (digit >= '0' && digit <= '9')
+		return digit - '0';
+	if (digit >= 'a' && digit <= 'f')
+		return 10 + digit - 'a';
+	if (digit >= 'A' && digit <= 'F')
+		return 10 + digit - 'A';
+
+	return -1;
+}
+
+static void _dequote_bytea_hex(char *string, STRLEN *retlen, int estring)
+{
+	dTHX;
+	char *result;
+
+	(*retlen) = 0;
+
+	if (NULL == string)
+		return;
+
+	result = string;
+
+	while (*string != '\0') {
+		int digit1, digit2;
+		digit1 = _decode_hex_digit(*string);
+		digit2 = _decode_hex_digit(*(string+1));
+		if (digit1 >= 0 && digit2 >= 0) {
+			*result++ = 16 * digit1 + digit2;
+			(*retlen)++;
+		}
+		string += 2;
+	}
+	*result = '\0';
+	return;
+}
+
+void dequote_bytea(char *string, STRLEN *retlen, int estring)
+{
+	dTHX;
+
+	if (NULL == string)
+		return;
+
+	if ('\\' == *string && 'x' == *(string+1))
+		return _dequote_bytea_hex(string, retlen, estring);
+	else
+		return _dequote_bytea_escape(string, retlen, estring);
+}
+
 /*
 	This one is not used in PG, but since we have a quote_sql_binary,
 	it might be nice to let people go the other way too. Say when talking

Modified: DBD-Pg/trunk/t/03dbmethod.t
==============================================================================
--- DBD-Pg/trunk/t/03dbmethod.t	(original)
+++ DBD-Pg/trunk/t/03dbmethod.t	Fri Oct  8 22:33:58 2010
@@ -1402,8 +1402,6 @@
 ok (!$result, $t);
 $dbh->rollback();
 
-my $abctext = $pgversion >= 80500 ? 'x6162630a646566' : "abc\ndef";
-
 SKIP: {
 
 	eval {
@@ -1422,7 +1420,7 @@
 	$t='DB handle method "pg_lo_import" inserts correct data';
 	$SQL = "SELECT data FROM pg_largeobject where loid = $handle";
 	$info = $dbh->selectall_arrayref($SQL)->[0][0];
-	is_deeply ($info, $abctext, $t);
+	is_deeply ($info, "abc\ndef", $t);
 	$dbh->commit();
 
   SKIP: {
@@ -1444,7 +1442,7 @@
 		$t='DB handle method "pg_lo_import_with_oid" inserts correct data';
 		$SQL = "SELECT data FROM pg_largeobject where loid = $thandle";
 		$info = $dbh->selectall_arrayref($SQL)->[0][0];
-		is_deeply ($info, $abctext, $t);
+		is_deeply ($info, "abc\ndef", $t);
 
 		$t='DB handle method "pg_lo_import_with_oid" fails when given already used number';
 		eval {
@@ -1558,7 +1556,7 @@
 	$sth = $dbh->prepare($SQL);
 	$sth->execute($handle);
 	$info = $sth->fetchall_arrayref()->[0][0];
-	is_deeply ($info, $abctext, $t);
+	is_deeply ($info, "abc\ndef", $t);
 
 	$t='DB handle method "pg_lo_import" works (AutoCommit on, begin_work called, no command)';
 	$dbh->begin_work();
@@ -1566,7 +1564,7 @@
 	ok ($handle, $t);
 	$sth->execute($handle);
 	$info = $sth->fetchall_arrayref()->[0][0];
-	is_deeply ($info, $abctext, $t);
+	is_deeply ($info, "abc\ndef", $t);
 	$dbh->rollback();
 
 	$t='DB handle method "pg_lo_import" works (AutoCommit on, begin_work called, no command, rollback)';
@@ -1585,7 +1583,7 @@
 	ok ($handle, $t);
 	$sth->execute($handle);
 	$info = $sth->fetchall_arrayref()->[0][0];
-	is_deeply ($info, $abctext, $t);
+	is_deeply ($info, "abc\ndef", $t);
 	$dbh->rollback();
 
 	$t='DB handle method "pg_lo_import" works (AutoCommit on, begin_work called, second command, rollback)';
@@ -1605,7 +1603,7 @@
 	ok ($handle, $t);
 	$sth->execute($handle);
 	$info = $sth->fetchall_arrayref()->[0][0];
-	is_deeply ($info, $abctext, $t);
+	is_deeply ($info, "abc\ndef", $t);
 
 	$t='DB handle method "pg_lo_import" works (AutoCommit not on, second command)';
 	$dbh->rollback();
@@ -1614,7 +1612,7 @@
 	ok ($handle, $t);
 	$sth->execute($handle);
 	$info = $sth->fetchall_arrayref()->[0][0];
-	is_deeply ($info, $abctext, $t);
+	is_deeply ($info, "abc\ndef", $t);
 
 	unlink $filename;
 	$dbh->{AutoCommit} = 1;

Modified: DBD-Pg/trunk/t/06bytea.t
==============================================================================
--- DBD-Pg/trunk/t/06bytea.t	(original)
+++ DBD-Pg/trunk/t/06bytea.t	Fri Oct  8 22:33:58 2010
@@ -17,7 +17,7 @@
 if (! $dbh) {
 	plan skip_all => 'Connection to database failed, cannot continue testing';
 }
-plan tests => 11;
+plan tests => 16;
 
 isnt ($dbh, undef, 'Connect to database for bytea testing');
 
@@ -26,10 +26,6 @@
 	$dbh->do('SET escape_string_warning = false');
 }
 
-if ($pgversion >= 90000) {
-	$dbh->do(q{SET bytea_output = 'escape'});
-}
-
 my ($sth, $t);
 
 $sth = $dbh->prepare(q{INSERT INTO dbd_pg_test (id,bytetest) VALUES (?,?)});
@@ -53,31 +49,48 @@
 $sth->{pg_server_prepare} = 1;
 ok ($sth->execute(404, $binary_out), $t);
 
-$t='Received correct text from BYTEA column with backslashes';
-$sth = $dbh->prepare(q{SELECT bytetest FROM dbd_pg_test WHERE id=?});
-$sth->execute(400);
-my $byte = $sth->fetchall_arrayref()->[0][0];
-is ($byte, 'aa\bb\cc\\\0dd\\', $t);
-
-$t='Received correct text from BYTEA column with quote';
-$sth->execute(402);
-$byte = $sth->fetchall_arrayref()->[0][0];
-is ($byte, '\'', $t);
-
-$t='Ensure proper handling of high bit characters';
-$sth->execute(403);
-($binary_in) = $sth->fetchrow_array();
-ok ($binary_in eq $binary_out, $t);
-$sth->execute(404);
-($binary_in) = $sth->fetchrow_array();
-ok ($binary_in eq $binary_out, $t);
-
-$t='quote properly handles bytea strings';
-my $string = "abc\123\\def\0ghi";
-my $result = $dbh->quote($string, { pg_type => PG_BYTEA });
-my $E = $pgversion >= 80100 ? q{E} : q{};
-my $expected = qq{${E}'abc\123\\\\\\\\def\\\\000ghi'};
-is ($result, $expected, $t);
+my @output;
+if ($pgversion >= 90000) {
+	@output = qw(hex escape);
+}
+else {
+	@output = (undef);
+	SKIP: { skip 'No BYTEA output format setting before 9.0', 5 }
+}
+
+for my $output (@output) {
+	$dbh->do(qq{SET bytea_output = '$output'}) if $output;
+
+	$t='Received correct text from BYTEA column with backslashes';
+	$t.=" ($output output)" if $output;
+	$sth = $dbh->prepare(q{SELECT bytetest FROM dbd_pg_test WHERE id=?});
+	$sth->execute(400);
+	my $byte = $sth->fetchall_arrayref()->[0][0];
+	is ($byte, 'aa\bb\cc\\\0dd\\', $t);
+
+	$t='Received correct text from BYTEA column with quote';
+	$t.=" ($output output)" if $output;
+	$sth->execute(402);
+	$byte = $sth->fetchall_arrayref()->[0][0];
+	is ($byte, '\'', $t);
+
+	$t='Ensure proper handling of high bit characters';
+	$t.=" ($output output)" if $output;
+	$sth->execute(403);
+	($binary_in) = $sth->fetchrow_array();
+	ok ($binary_in eq $binary_out, $t);
+	$sth->execute(404);
+	($binary_in) = $sth->fetchrow_array();
+	ok ($binary_in eq $binary_out, $t);
+
+	$t='quote properly handles bytea strings';
+	$t.=" ($output output)" if $output;
+	my $string = "abc\123\\def\0ghi";
+	my $result = $dbh->quote($string, { pg_type => PG_BYTEA });
+	my $E = $pgversion >= 80100 ? q{E} : q{};
+	my $expected = qq{${E}'abc\123\\\\\\\\def\\\\000ghi'};
+	is ($result, $expected, $t);
+}
 
 $sth->finish();
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.