Committed by =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= <[email protected]>

Subject: [DBD::Pg 2/8] Add support for UTF-8 statement strings

---
 dbdimp.c      |  5 ++++-
 dbdimp.h      |  4 ++--
 t/30unicode.t | 58 ++++++++++++++++++++++++++++++++++++----------------------
 3 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/dbdimp.c b/dbdimp.c
index fed72bd..59e2f61 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -1530,13 +1530,16 @@ SV * pg_db_pg_notifies (SV * dbh, imp_dbh_t * imp_dbh)
 
 
 /* ================================================================== */
-int dbd_st_prepare (SV * sth, imp_sth_t * imp_sth, char * statement, SV * 
attribs)
+int dbd_st_prepare_sv (SV * sth, imp_sth_t * imp_sth, SV * statement_sv, SV * 
attribs)
 {
        dTHX;
        D_imp_dbh_from_sth;
        STRLEN mypos=0, wordstart, newsize; /* Used to find and set firstword */
        SV **svp; /* To help parse the arguments */
 
+       statement_sv = pg_rightgraded_sv(aTHX_ statement_sv, 
imp_dbh->client_encoding_utf8);
+       char *statement = SvPV_nolen(statement_sv);
+
        if (TSTART_slow) TRC(DBILOGFP, "%sBegin dbd_st_prepare (statement: 
%s)\n", THEADER_slow, statement);
 
        if ('\0' == *statement)
diff --git a/dbdimp.h b/dbdimp.h
index abc082a..5e4f72f 100644
--- a/dbdimp.h
+++ b/dbdimp.h
@@ -158,8 +158,8 @@ int dbd_st_STORE_attrib (SV * sth, imp_sth_t * imp_sth, SV 
* keysv, SV * valuesv
 #define dbd_discon_all  pg_discon_all
 int dbd_discon_all (SV * drh, imp_drh_t * imp_drh);
 
-#define dbd_st_prepare  pg_st_prepare
-int dbd_st_prepare (SV * sth, imp_sth_t * imp_sth, char * statement, SV * 
attribs);
+#define dbd_st_prepare_sv  pg_st_prepare_sv
+int dbd_st_prepare_sv (SV * sth, imp_sth_t * imp_sth, SV * statement_sv, SV * 
attribs);
 
 #define dbd_bind_ph pg_bind_ph
 int dbd_bind_ph (SV * sth, imp_sth_t * imp_sth, SV * ph_name, SV * newvalue, 
IV sql_type, SV * attribs, int is_inout, IV maxlen);
diff --git a/t/30unicode.t b/t/30unicode.t
index ad45fc5..bec7d12 100644
--- a/t/30unicode.t
+++ b/t/30unicode.t
@@ -9,7 +9,7 @@ use strict;
 use warnings;
 use utf8;
 use charnames ':full';
-use Encode;
+use Encode qw(encode_utf8);
 use Test::More;
 use lib 't','.';
 require 'dbdpg_test_setup.pl';
@@ -29,33 +29,47 @@ my $name_d = my $name_u = "\N{LATIN CAPITAL LETTER E WITH 
ACUTE}milie du Ch\N{LA
 utf8::downgrade($name_d);
 utf8::upgrade($name_u);
 
+# Before 5.12.0 the text to the left of => gets to be SvUTF8() under use utf8;
+# even if it's plain ASCII. This would confuse what we test for below.
 foreach (
-    [upgraded => text => $name_u],
-    [downgraded => text => $name_d],
+    [upgraded => 'text' => $name_u],
+    [downgraded => 'text' => $name_d],
     [upgraded => 'text[]' => [$name_u]],
     [downgraded => 'text[]' => [$name_d]],
     [mixed => 'text[]' => [$name_d,$name_u]],
 ) {
     my ($state, $type, $value) = @$_;
-    $dbh->{pg_enable_utf8} = 1;
-
-    my $SQL = "SELECT ?::$type";
-    my $sth = $dbh->prepare($SQL);
-    $sth->execute($value);
-    my $result = $sth->fetchall_arrayref->[0][0];
-    $t = "Fetching $state UTF-8 $type from the database returns proper value";
-    is_deeply ($result, $value, $t);
-    $t = "Fetching $state UTF-8 $type from the database returns string with 
UTF-8 flag on";
-    ok (utf8::is_utf8($_), $t) for (ref $result ? @{$result} : $result);
-
-    $dbh->{pg_enable_utf8} = 0;
-    $sth->execute($value);
-    $result = $sth->fetchall_arrayref->[0][0];
-    $t = "Fetching $state UTF-8 $type from the database returns proper string 
(pg_enable_utf8=0)";
-    utf8::encode($_) for (ref $value ? @{$value} : $value);
-    is_deeply ($result, $value, $t);
-    $t = "Fetching $state UTF-8 $type from the database returns string with 
UTF-8 flag off (pg_enable_utf8=0)";
-    ok (!utf8::is_utf8($result), $t) for (ref $result ? @{$result} : $result);
+    foreach (
+        [placeholder => "SELECT ?::$type", $value],
+        (($type eq 'text') ? (
+            [interpolated => "SELECT '$value'::$type"],
+        ):()),
+    ) {
+        foreach my $enable_utf8 (1, 0) {
+            my ($qtype, $sql, @args) = @$_;
+            my $desc = "$state UTF-8 $qtype $type 
(pg_enable_utf8=$enable_utf8)";
+            is(utf8::is_utf8($sql), ($state eq 'upgraded'), "$desc query has 
correct flag")
+                if $qtype eq 'interpolated';
+            if ($state ne 'mixed') {
+                foreach my $arg (map { ref($_) ? @{$_} : $_ } @args) {
+                    is(utf8::is_utf8($arg), ($state eq 'upgraded'), "$desc arg 
has correct flag")
+                }
+            }
+            $dbh->{pg_enable_utf8} = $enable_utf8;
+
+            my $sth = $dbh->prepare($sql);
+            $sth->execute(@args);
+            my $result = $sth->fetchall_arrayref->[0][0];
+            my $return_value =
+                $enable_utf8 ? $value :
+                ref $value   ? [ map encode_utf8($_), @{$value} ] :
+                encode_utf8($value);
+            $t = "$desc returns proper value";
+            is_deeply ($result, $return_value, $t);
+            $t = "$desc returns string with correct UTF-8 flag ";
+            is(utf8::is_utf8($_), !!$enable_utf8, $t) for (ref $result ? 
@{$result} : $result);
+        }
+    }
 }
 
 $t = 'Generated string is not utf8';
-- 
1.8.4

Reply via email to