Author: turnstep
Date: Thu May  8 19:14:39 2008
New Revision: 11220

Modified:
   DBD-Pg/trunk/.perlcriticrc
   DBD-Pg/trunk/Changes
   DBD-Pg/trunk/Pg.pm
   DBD-Pg/trunk/Pg.xs
   DBD-Pg/trunk/dbdimp.c
   DBD-Pg/trunk/dbdimp.h
   DBD-Pg/trunk/quote.c
   DBD-Pg/trunk/t/02attribs.t
   DBD-Pg/trunk/t/03dbmethod.t
   DBD-Pg/trunk/t/06bytea.t
   DBD-Pg/trunk/t/12placeholders.t
   DBD-Pg/trunk/t/99_spellcheck.t

Log:
Handle backslashes in quoting by using E'' when possible.
Adjust tests for new E''
Flesh out quote() docs a bit.
Don't track standard_conforming_strings at low-level anymore.
Remove mention of pg_auto_escape parameter.


Modified: DBD-Pg/trunk/.perlcriticrc
==============================================================================
--- DBD-Pg/trunk/.perlcriticrc  (original)
+++ DBD-Pg/trunk/.perlcriticrc  Thu May  8 19:14:39 2008
@@ -2,7 +2,7 @@
 profile-strictness = quiet
 
 [Documentation::PodSpelling]
-stop_words = ActiveKids AutoCommit CachedKids ChildHandles ChopBlanks 
CompatMode CursorName DBD DBI Datatype dbdpg ErrCount FetchHashKeyName 
HandleError HandleSetErr InactiveDestroy LongReadLen LongTruncOk Mergl Momjian 
Mullane NULLABLE OID PgBouncer pgend pglibpq pglogin pgprefix pgquote pgstart 
Postgres PostgreSQL PrintError PrintWarn README RaiseError RowCache 
RowCacheSize SQL SQLSTATE SSL STDIN STDERR STDOUT Sabino Savepoints 
ShowErrorStatement TaintIn TaintOut TraceLevel UTF Username afterwards 
arrayrefs attr autocommit backend bitmask cancelled datatype dbd dbh errstr fd 
filename getfd getline largeobject len libpq pgbuiltin pgsql runtime savepoint 
savepoints schemas sslmode tablename tablespace tablespaces tuple typename 
username varchar
+stop_words = ActiveKids AutoCommit CachedKids ChildHandles ChopBlanks 
CompatMode CursorName DBD DBI Datatype dbdpg ErrCount FetchHashKeyName 
HandleError HandleSetErr InactiveDestroy LongReadLen LongTruncOk Mergl Momjian 
Mullane NULLABLE OID PgBouncer pgend pglibpq pglogin pgprefix pgquote pgstart 
Postgres PostgreSQL PrintError PrintWarn README RaiseError RowCache 
RowCacheSize SQL SQLSTATE SSL STDIN STDERR STDOUT Sabino Savepoints 
ShowErrorStatement TaintIn TaintOut TraceLevel UTF Username afterwards 
arrayrefs attr autocommit backend bitmask bytea cancelled datatype dbd dbh 
errstr fd filename getfd getline largeobject len libpq lseg pgbuiltin pgsql 
runtime savepoint savepoints schemas sslmode tablename tablespace tablespaces 
tuple typename username varchar
 
 [-Bangs::ProhibitCommentedOutCode]
 [-Bangs::ProhibitFlagComments]

Modified: DBD-Pg/trunk/Changes
==============================================================================
--- DBD-Pg/trunk/Changes        (original)
+++ DBD-Pg/trunk/Changes        Thu May  8 19:14:39 2008
@@ -1,5 +1,12 @@
 ('GSM' is Greg Sabino Mullane, [EMAIL PROTECTED])
 
+2.7.0
+
+       - Have $dbh->quote() return E'' when server is >= 8.1
+               and string contains backslashes. Fixes any 
+               problems with standard_conforming_strings.
+               (CPAN bug #27538) [GSM]
+
 2.6.6 Released May 7, 2008 (subversion r11214)
 
        - Fix minor problem in t/99_spellcheck.t

Modified: DBD-Pg/trunk/Pg.pm
==============================================================================
--- DBD-Pg/trunk/Pg.pm  (original)
+++ DBD-Pg/trunk/Pg.pm  Thu May  8 19:14:39 2008
@@ -2750,10 +2750,20 @@
 
   $rv = $dbh->quote($value, $data_type);
 
-This module implements its own C<quote> method. In addition to the DBI method 
it
-also doubles the backslash, because PostgreSQL treats a backslash as an escape
-character. You may also quote arrayrefs and received a string suitable for 
-passing into Postgres array columns.
+This module implements its own C<quote> method. For simple string types, both 
backslashes 
+and single quotes are doubled. You may also quote arrayrefs and receive a 
string 
+suitable for passing into Postgres array columns.
+
+If the value contains backslashes, and the server is version 8.1 or higher, 
+then the escaped string syntax will be used (which places a capital E before 
+the first single quote). This syntax is always used when quoting bytea values 
+on servers 8.1 and higher.
+
+The C<data_type> argument is optional and should be one of the type constants 
+exported by DBD::Pg (such as PG_BYTEA). In addition to string, bytea, char, 
bool, 
+and other standard types, the following geometric types are supported: point, 
line, 
+lseg, box, path, polygon, and circle (PG_POINT, PG_LINE, PG_LSEG, PG_BOX, 
+PG_POLYGON, and PG_CIRCLE).
 
 B<NOTE:> The undocumented (and invalid) support for the C<SQL_BINARY> data
 type is officially deprecated. Use C<PG_BYTEA> with C<bind_param()> instead:
@@ -2830,18 +2840,6 @@
 
 Supported by this driver as proposed by DBI.
 
-=item B<pg_auto_escape> (boolean)
-
-PostgreSQL specific attribute. If true, then quotes and backslashes in all
-parameters will be escaped in the following way:
-
-  escape quote with a quote (SQL)
-  escape backslash with a backslash
-
-The default is on. Note that PostgreSQL also accepts quotes that are
-escaped by a backslash. Any other ASCII character can be used directly in a
-string constant.
-
 =item B<pg_enable_utf8> (boolean)
 
 PostgreSQL specific attribute. If true, then the C<utf8> flag will be turned

Modified: DBD-Pg/trunk/Pg.xs
==============================================================================
--- DBD-Pg/trunk/Pg.xs  (original)
+++ DBD-Pg/trunk/Pg.xs  Thu May  8 19:14:39 2008
@@ -248,7 +248,7 @@
                                
                        to_quote = SvPV(to_quote_sv, len);
                        /* Need good debugging here */
-                       quoted = type_info->quote(to_quote, len, &retlen, 0);
+                       quoted = type_info->quote(to_quote, len, &retlen, 
imp_dbh->pg_server_version >= 80100 ? 1 : 0);
                        RETVAL = newSVpvn(quoted, retlen);
                        if (SvUTF8(to_quote_sv)) /* What about overloaded 
objects? */
                                SvUTF8_on(RETVAL);

Modified: DBD-Pg/trunk/dbdimp.c
==============================================================================
--- DBD-Pg/trunk/dbdimp.c       (original)
+++ DBD-Pg/trunk/dbdimp.c       Thu May  8 19:14:39 2008
@@ -216,16 +216,6 @@
                }
        }
 
-       /* Check the status of standard_conforming_strings */
-       imp_dbh->standard_escape = DBDPG_FALSE;
-       if (imp_dbh->pg_server_version >= 80100) { /* cannot be true until 8.1 
*/
-               TRACE_PQPARAMETERSTATUS;
-               if (NULL != PQparameterStatus(imp_dbh->conn, 
"standard_conforming_strings")
-                       && 0==strncmp("on", PQparameterStatus(imp_dbh->conn, 
"standard_conforming_strings"), 2)) {
-                       imp_dbh->standard_escape = DBDPG_TRUE;
-               }
-       }
-
        imp_dbh->pg_bool_tf      = DBDPG_FALSE;
        imp_dbh->pg_enable_utf8  = DBDPG_FALSE;
        imp_dbh->prepare_now     = DBDPG_FALSE;
@@ -2825,8 +2815,12 @@
                        else {
                                if (currph->quoted)
                                        Safefree(currph->quoted);
-                               currph->quoted = currph->bind_type->quote
-                                       (currph->value, currph->valuelen, 
&currph->quotedlen, 0); /* freed in dbd_st_destroy */
+                               currph->quoted = currph->bind_type->quote(
+                                       currph->value,
+                                       currph->valuelen,
+                                       &currph->quotedlen,
+                                       imp_dbh->pg_server_version >= 80100 ? 1 
: 0
+                                                                               
                                  ); /* freed in dbd_st_destroy */
                        }
                }
                /* Set the size of each actual in-place placeholder */

Modified: DBD-Pg/trunk/dbdimp.h
==============================================================================
--- DBD-Pg/trunk/dbdimp.h       (original)
+++ DBD-Pg/trunk/dbdimp.h       Thu May  8 19:14:39 2008
@@ -24,7 +24,6 @@
        bool    done_begin;        /* have we done a begin? (e.g. are we in a 
transaction?) */
        bool    dollaronly;        /* Only consider $1, $2 ... as valid 
placeholders */
        bool    expand_array;      /* Transform arrays from the db into Perl 
arrays? Default is 1 */
-       bool    standard_escape;   /* Is standard_conforming_strings turned on? 
*/
 
        int     pg_protocol;       /* value of PQprotocolVersion, usually 3 
(could also be 0) */
        int     pg_server_version; /* Server version e.g. 80100 */

Modified: DBD-Pg/trunk/quote.c
==============================================================================
--- DBD-Pg/trunk/quote.c        (original)
+++ DBD-Pg/trunk/quote.c        Thu May  8 19:14:39 2008
@@ -11,6 +11,12 @@
 
 #include "Pg.h"
 
+/*
+The 'estring' indicates if the server is capable of using the E'' syntax
+In other words, is it 8.1 or better?
+It must arrive as 0 or 1
+*/
+
 char * null_quote(const char *string, STRLEN len, STRLEN *retlen, int estring)
 {
        dTHX;
@@ -31,24 +37,28 @@
        STRLEN oldlen = len;
        const char * const tmp = string;
 
-       (*retlen) = estring ? 3 : 2;
+       (*retlen) = 2;
        while (len > 0 && *string != '\0') {
-               if (*string == '\'' || *string == '\\') {
+               if (*string == '\'')
+                       (*retlen)++;
+               else if (*string == '\\') {
+                       if (estring == 1)
+                               estring = 2;
                        (*retlen)++;
                }
                (*retlen)++;
                string++;
                len--;
        }
+       if (estring == 2)
+               (*retlen)++;
+
        string = tmp;
        New(0, result, 1+(*retlen), char);
-       if (estring) {
+       if (estring == 2)
                *result++ = 'E';
-               *result++ = '\'';
-       }
-       else {
-               *result++ = '\'';
-       }
+       *result++ = '\'';
+
        len = oldlen;
        while (len > 0 && *string != '\0') {
                if (*string == '\'' || *string == '\\') {
@@ -71,7 +81,7 @@
 
        len = 0; /* stops compiler warnings. Remove entirely someday */
        tmp = string;
-       (*retlen) = estring ? 3 : 2;
+       (*retlen) = 2;
        while (*string != '\0') {
                if (*string !=9 && *string != 32 && *string != '(' && *string 
!= ')'
                        && *string != ',' && (*string < '0' || *string > '9'))
@@ -81,13 +91,8 @@
        }
        string = tmp;
        New(0, result, 1+(*retlen), char);
-       if (estring) {
-               *result++ = 'E';
-               *result++ = '\'';
-       }
-       else {
-               *result++ = '\'';
-       }
+       *result++ = '\'';
+
        while (*string != '\0') {
                *result++ = *string++;
        }
@@ -103,7 +108,7 @@
        const char * const tmp = string;
 
        len = 0; /* stops compiler warnings. Remove entirely someday */
-       (*retlen) = estring ? 3 : 2;
+       (*retlen) = 2;
        while (*string != '\0') {
                if (*string !=9 && *string != 32 && *string != '(' && *string 
!= ')'
                        && *string != ',' && *string != '[' && *string != ']'
@@ -114,13 +119,8 @@
        }
        string = tmp;
        New(0, result, 1+(*retlen), char);
-       if (estring) {
-               *result++ = 'E';
-               *result++ = '\'';
-       }
-       else {
-               *result++ = '\'';
-       }
+       *result++ = '\'';
+
        while (*string != '\0') {
                *result++ = *string++;
        }
@@ -136,7 +136,7 @@
        const char * const tmp = string;
 
        len = 0; /* stops compiler warnings. Remove entirely someday */
-       (*retlen) = estring ? 3 : 2;
+       (*retlen) = 2;
        while (*string != '\0') {
                if (*string !=9 && *string != 32 && *string != '(' && *string 
!= ')'
                        && *string != ',' && *string != '<' && *string != '>'
@@ -147,13 +147,8 @@
        }
        string = tmp;
        New(0, result, 1+(*retlen), char);
-       if (estring) {
-               *result++ = 'E';
-               *result++ = '\'';
-       }
-       else {
-               *result++ = '\'';
-       }
+       *result++ = '\'';
+
        while (*string != '\0') {
                *result++ = *string++;
        }
@@ -169,8 +164,9 @@
        char * result;
        STRLEN oldlen = len;
 
+       /* For this one, always use the E'' format if we can */
        result = string;
-       (*retlen) = estring ? 3 : 2;
+       (*retlen) = 2;
        while (len > 0) {
                if (*string == '\'') {
                        (*retlen) += 2;
@@ -188,14 +184,14 @@
                len--;
        }
        string = result;
+       if (estring)
+               (*retlen)++;
+
        New(0, result, 1+(*retlen), char);
-       if (estring) {
+       if (estring)
                *result++ = 'E';
-               *result++ = '\'';
-       }
-       else {
-               *result++ = '\'';
-       }
+       *result++ = '\'';
+
        len = oldlen;
        while (len > 0) {
                if (*string == '\'') { /* Single quote becomes double quotes */

Modified: DBD-Pg/trunk/t/02attribs.t
==============================================================================
--- DBD-Pg/trunk/t/02attribs.t  (original)
+++ DBD-Pg/trunk/t/02attribs.t  Thu May  8 19:14:39 2008
@@ -16,10 +16,12 @@
 if (! defined $dbh) {
        plan skip_all => 'Connection to database failed, cannot continue 
testing';
 }
-plan tests => 131;
+plan tests => 137;
 
 isnt( $dbh, undef, 'Connect to database for handle attributes testing');
 
+my ($pglibversion,$pgversion) = 
($dbh->{pg_lib_version},$dbh->{pg_server_version});
+
 my $attributes_tested = q{
 
 d = database handle specific
@@ -320,6 +322,32 @@
 $result = $dbh->{pg_pid};
 like( $result, qr/^\d+$/, q{DB handle attribute "pg_pid" returns a value});
 
+SKIP: {
+
+       skip 'Cannot test standard_conforming_strings on pre 8.1 servers', 5;
+
+       $t=q{DB handle attribute "pg_standard_conforming_strings" returns a 
valid value};
+       my $oldscs = $dbh->{pg_standard_conforming_strings};
+       like( $oldscs, qr/^on|off$/, $t);
+
+       $dbh->do('SET standard_conforming_strings = on');
+       $t=q{DB handle attribute "pg_standard_conforming_strings" returns 
correct value};
+       $result = $dbh->{pg_standard_conforming_strings};
+       is( $result, 'on', $t);
+       $t=q{DB handle attribute "pg_scs" returns correct value};
+       $result = $dbh->{pg_scs};
+       is( $result, 'on', $t);
+
+       $dbh->do('SET standard_conforming_strings = off');
+       $t=q{DB handle attribute "pg_standard_conforming_strings" returns 
correct value};
+       $result = $dbh->{pg_standard_conforming_strings};
+       is( $result, 'off', $t);
+       $t=q{DB handle attribute "pg_scs" returns correct value};
+       $result = $dbh->{pg_scs};
+       is( $result, 'off', $t);
+       $dbh->do("SET standard_conforming_strings = $oldscs");
+}
+
 ## If Encode is available, we will insert some non-ASCII into the test table
 ## Since this will fail with client encodings such as BIG5, we force UTF8
 my $old_encoding = $dbh->selectall_arrayref('SHOW client_encoding')->[0][0];
@@ -336,7 +364,7 @@
        $sth->execute(1);
        local $dbh->{pg_enable_utf8} = 1;
        my $utf8_str = chr(0x100).'dam'; # LATIN CAPITAL LETTER A WITH MACRON
-
+       is( $dbh->quote( $utf8_str ),  "'$utf8_str'", $t);
        $SQL = "INSERT INTO dbd_pg_test (id, pname, val) VALUES (40, 
'$utf8_str', 'Orange')";
        is( $dbh->do($SQL), '1', 'Able to insert unicode character into the 
database');
        $sth->execute(40);

Modified: DBD-Pg/trunk/t/03dbmethod.t
==============================================================================
--- DBD-Pg/trunk/t/03dbmethod.t (original)
+++ DBD-Pg/trunk/t/03dbmethod.t Thu May  8 19:14:39 2008
@@ -25,7 +25,7 @@
 if (! defined $dbh) {
        plan skip_all => 'Connection to database failed, cannot continue 
testing';
 }
-plan tests => 220;
+plan tests => 222;
 
 isnt( $dbh, undef, 'Connect to database for database handle method testing');
 
@@ -999,6 +999,14 @@
 }
 is( $dbh->quote(1, 4), 1, 'DB handle method "quote" works with a supplied data 
type argument');
 
+## Various backslash tests
+my $E = $pgversion >= 80100 ? q{E} : q{};
+$t=q{DB handle method "quote" works properly with backslashes};
+is( $dbh->quote('foo\\bar'), qq{${E}'foo\\\\bar'}, $t);
+
+$t=q{DB handle method "quote" works properly without backslashes};
+is( $dbh->quote('foobar'), q{'foobar'}, $t);
+
 #
 # Test various quote types
 #

Modified: DBD-Pg/trunk/t/06bytea.t
==============================================================================
--- DBD-Pg/trunk/t/06bytea.t    (original)
+++ DBD-Pg/trunk/t/06bytea.t    Thu May  8 19:14:39 2008
@@ -46,7 +46,8 @@
 
 my $string = "abc\123\\def\0ghi";
 my $result = $dbh->quote($string, { pg_type => PG_BYTEA });
-my $expected = qq{'abc\123\\\\\\\\def\\\\000ghi'};
+my $E = $pgversion >= 80100 ? q{E} : q{};
+my $expected = qq{${E}'abc\123\\\\\\\\def\\\\000ghi'};
 is( $result, $expected, 'quote properly handles bytea strings.');
 
 $sth->finish();

Modified: DBD-Pg/trunk/t/12placeholders.t
==============================================================================
--- DBD-Pg/trunk/t/12placeholders.t     (original)
+++ DBD-Pg/trunk/t/12placeholders.t     Thu May  8 19:14:39 2008
@@ -25,9 +25,10 @@
 }
 
 # Make sure that quoting works properly.
+my $E = $pgversion >= 80100 ? q{E} : q{};
 $t=q{Quoting works properly};
 my $quo = $dbh->quote('\\\'?:');
-is( $quo, q{'\\\\''?:'}, $t);
+is( $quo, qq{${E}'\\\\''?:'}, $t);
 
 $t=q{Quoting works with a function call};
 # Make sure that quoting works with a function call.
@@ -134,7 +135,9 @@
 my $backslash = $dbh->selectall_arrayref($SQL)->[0][0];
 
 $t=q{Prepare with backslashes inside quotes works};
-$sth = $dbh->prepare(q{SELECT '\\'?'});
+my $scs = $dbh->{pg_scs};
+$SQL = $scs ? q{SELECT E'\\'?'} : q{SELECT '\\'?'};
+$sth = $dbh->prepare($SQL);
 eval {
        $sth->execute();
 };

Modified: DBD-Pg/trunk/t/99_spellcheck.t
==============================================================================
--- DBD-Pg/trunk/t/99_spellcheck.t      (original)
+++ DBD-Pg/trunk/t/99_spellcheck.t      Thu May  8 19:14:39 2008
@@ -593,6 +593,7 @@
 qw
 
 ## Pg.pm:
+lseg
 afterwards
 
 ## Pg.xs:
@@ -670,6 +671,7 @@
 ph
 
 ## quote.c:
+estring
 SVs
 compat
 

Reply via email to