diff --git a/Database/PostgreSQL/Typed/Protocol.hs b/Database/PostgreSQL/Typed/Protocol.hs
--- a/Database/PostgreSQL/Typed/Protocol.hs
+++ b/Database/PostgreSQL/Typed/Protocol.hs
@@ -707,6 +707,7 @@
     , ("bytea_output", "hex")
     , ("DateStyle", "ISO, YMD")
     , ("IntervalStyle", "iso_8601")
+    , ("extra_float_digits", "3")
     ] ++ pgDBParams db
   pgFlush c
   conn c
diff --git a/Database/PostgreSQL/Typed/Query.hs b/Database/PostgreSQL/Typed/Query.hs
--- a/Database/PostgreSQL/Typed/Query.hs
+++ b/Database/PostgreSQL/Typed/Query.hs
@@ -25,6 +25,8 @@
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Char8 as BSC
 import qualified Data.ByteString.Lazy as BSL
+import qualified Data.ByteString.Lazy.UTF8 as BSLU
+import qualified Data.ByteString.UTF8 as BSU
 import Data.Char (isSpace, isAlphaNum)
 import qualified Data.Foldable as Fold
 import Data.List (dropWhileEnd)
@@ -148,7 +150,7 @@
     | inRange bnds n = exprs ! n
     | otherwise = error $ "SQL placeholder '$" ++ show n ++ "' out of range (not recognized by PostgreSQL)"
   sst (SQLParam n) = expr n
-  sst t = TH.VarE 'fromString `TH.AppE` TH.LitE (TH.StringL $ show t)
+  sst t = TH.VarE 'BSU.fromString `TH.AppE` TH.LitE (TH.StringL $ show t)
 
 splitCommas :: String -> [String]
 splitCommas = spl where
@@ -185,7 +187,7 @@
 makePGQuery :: QueryFlags -> String -> TH.ExpQ
 makePGQuery QueryFlags{ flagQuery = False } sqle = pgSubstituteLiterals sqle
 makePGQuery QueryFlags{ flagNullable = nulls, flagPrepare = prep } sqle = do
-  (pt, rt) <- TH.runIO $ tpgDescribe (fromString sqlp) (fromMaybe [] prep) (isNothing nulls)
+  (pt, rt) <- TH.runIO $ tpgDescribe (BSU.fromString sqlp) (fromMaybe [] prep) (isNothing nulls)
   when (length pt < length exprs) $ fail "Not all expression placeholders were recognized by PostgreSQL"
 
   e <- TH.newName "_tenv"
@@ -208,7 +210,7 @@
       (TH.ConE 'SimpleQuery
         `TH.AppE` sqlSubstitute sqlp vals)
       (\p -> TH.ConE 'PreparedQuery
-        `TH.AppE` (TH.VarE 'fromString `TH.AppE` TH.LitE (TH.StringL sqlp))
+        `TH.AppE` (TH.VarE 'BSU.fromString `TH.AppE` TH.LitE (TH.StringL sqlp))
         `TH.AppE` TH.ListE (map (TH.LitE . TH.IntegerL . toInteger . tpgValueTypeOID . snd) $ zip p pt)
         `TH.AppE` TH.ListE vals 
         `TH.AppE` TH.ListE 
@@ -255,7 +257,7 @@
 qqTop True ('!':sql) = qqTop False sql
 qqTop err sql = do
   r <- TH.runIO $ try $ withTPGConnection $ \c ->
-    pgSimpleQuery c (fromString sql)
+    pgSimpleQuery c (BSLU.fromString sql)
   either ((if err then TH.reportError else TH.reportWarning) . (show :: PGError -> String)) (const $ return ()) r
   return []
 
diff --git a/Database/PostgreSQL/Typed/Types.hs b/Database/PostgreSQL/Typed/Types.hs
--- a/Database/PostgreSQL/Typed/Types.hs
+++ b/Database/PostgreSQL/Typed/Types.hs
@@ -232,7 +232,9 @@
 
 -- |Produce a SQL string literal by wrapping (and escaping) a string with single quotes.
 pgQuote :: BS.ByteString -> BS.ByteString
-pgQuote = pgQuoteUnsafe . BSC.intercalate (BSC.pack "''") . BSC.split '\''
+pgQuote s
+  | '\0' `BSC.elem` s = error "pgQuote: unhandled null in literal"
+  | otherwise = pgQuoteUnsafe $ BSC.intercalate (BSC.pack "''") $ BSC.split '\'' s
 
 -- |Shorthand for @'BSL.toStrict' . 'BSB.toLazyByteString'@
 buildPGValue :: BSB.Builder -> BS.ByteString
diff --git a/postgresql-typed.cabal b/postgresql-typed.cabal
--- a/postgresql-typed.cabal
+++ b/postgresql-typed.cabal
@@ -1,5 +1,5 @@
 Name:          postgresql-typed
-Version:       0.6.1.2
+Version:       0.6.2.0
 Cabal-Version: >= 1.10
 License:       BSD3
 License-File:  COPYING
@@ -71,7 +71,7 @@
     template-haskell,
     haskell-src-meta,
     network,
-    attoparsec >= 0.12 && < 0.14,
+    attoparsec >= 0.12 && < 0.15,
     utf8-string
   Exposed-Modules:
     Database.PostgreSQL.Typed
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -5,8 +5,6 @@
 
 import Control.Exception (try)
 import Control.Monad (unless)
-import qualified Data.ByteString as BS
-import qualified Data.ByteString.Char8 as BSC
 import Data.Char (isDigit, toUpper)
 import Data.Int (Int32)
 import qualified Data.Time as Time
@@ -38,7 +36,8 @@
 -- This runs at compile-time:
 [pgSQL|!CREATE TYPE myenum AS enum ('abc', 'DEF', 'XX_ye')|]
 
-[pgSQL|!CREATE TABLE myfoo (id serial primary key, adx myenum, bar char(4))|]
+[pgSQL|!DROP TABLE myfoo|]
+[pgSQL|!CREATE TABLE myfoo (id serial primary key, adé myenum, bar float)|]
 
 dataPGEnum "MyEnum" "myenum" ("MyEnum_" ++)
 
@@ -46,11 +45,13 @@
 
 dataPGRelation "MyFoo" "myfoo" (\(c:s) -> "foo" ++ toUpper c : s)
 
-_fooRow :: MyFoo
-_fooRow = MyFoo{ fooId = 1, fooAdx = Just MyEnum_DEF, fooBar = Just "abcd" }
-
 instance Q.Arbitrary MyEnum where
   arbitrary = Q.arbitraryBoundedEnum
+instance Q.Arbitrary MyFoo where
+  arbitrary = MyFoo 0 <$> Q.arbitrary <*> Q.arbitrary
+instance Eq MyFoo where
+  MyFoo _ a b == MyFoo _ a' b' = a == a' && b == b'
+deriving instance Show MyFoo
 
 instance Q.Arbitrary Time.Day where
   arbitrary = Time.ModifiedJulianDay <$> Q.arbitrary
@@ -84,15 +85,15 @@
     , SQLExpr <$> Q.arbitrary
     , SQLQMark <$> Q.arbitrary
     ]
-    
-newtype Str = Str { strString :: [Char] } deriving (Eq, Show)
-strByte :: Str -> BS.ByteString
-strByte = BSC.pack . strString
-byteStr :: BS.ByteString -> Str
-byteStr = Str . BSC.unpack
-instance Q.Arbitrary Str where
-  arbitrary = Str <$> Q.listOf (Q.choose (' ', '~'))
 
+newtype SafeString = SafeString Q.UnicodeString
+  deriving (Eq, Ord, Show)
+instance Q.Arbitrary SafeString where
+  arbitrary = SafeString <$> Q.suchThat Q.arbitrary (notElem '\0' . Q.getUnicodeString)
+
+getSafeString :: SafeString -> String
+getSafeString (SafeString s) = Q.getUnicodeString s
+
 simple :: PGConnection -> OID -> IO [String]
 simple c t = pgQuery c [pgSQL|SELECT typname FROM pg_catalog.pg_type WHERE oid = ${t} AND oid = $1|]
 simpleApply :: PGConnection -> OID -> IO [Maybe String]
@@ -102,26 +103,60 @@
 preparedApply :: PGConnection -> Int32 -> IO [String]
 preparedApply c = pgQuery c . [pgSQL|$(integer)SELECT typname FROM pg_catalog.pg_type WHERE oid = $1|]
 
-selectProp :: PGConnection -> Bool -> Word8 -> Int32 -> Float -> Time.LocalTime -> Time.UTCTime -> Time.Day -> Time.DiffTime -> Str -> [Maybe Str] -> Range.Range Int32 -> MyEnum -> PGInet -> Q.Property
+selectProp :: PGConnection -> Bool -> Word8 -> Int32 -> Float -> Time.LocalTime -> Time.UTCTime -> Time.Day -> Time.DiffTime -> SafeString -> [Maybe SafeString] -> Range.Range Int32 -> MyEnum -> PGInet -> Q.Property
 selectProp pgc b c i f t z d p s l r e a = Q.ioProperty $ do
   [(Just b', Just c', Just i', Just f', Just s', Just d', Just t', Just z', Just p', Just l', Just r', Just e', Just a')] <- pgQuery pgc
-    [pgSQL|$SELECT ${b}::bool, ${c}::"char", ${Just i}::int, ${f}::float4, ${strString s}::varchar, ${Just d}::date, ${t}::timestamp, ${z}::timestamptz, ${p}::interval, ${map (fmap strByte) l}::text[], ${r}::int4range, ${e}::myenum, ${a}::inet|]
-  return $ Q.conjoin 
+    [pgSQL|$SELECT ${b}::bool, ${c}::"char", ${Just i}::int, ${f}::float4, ${getSafeString s}::varchar, ${Just d}::date, ${t}::timestamp, ${z}::timestamptz, ${p}::interval, ${map (fmap getSafeString) l}::text[], ${r}::int4range, ${e}::myenum, ${a}::inet|]
+  return $ Q.conjoin
     [ i Q.=== i'
     , c Q.=== c'
     , b Q.=== b'
-    , strString s Q.=== s'
+    , getSafeString s Q.=== s'
     , f Q.=== f'
     , d Q.=== d'
     , t Q.=== t'
     , z Q.=== z'
     , p Q.=== p'
-    , l Q.=== map (fmap byteStr) l'
+    , map (fmap getSafeString) l Q.=== l'
     , Range.normalize' r Q.=== r'
     , e Q.=== e'
     , a Q.=== a'
     ]
 
+selectProp' :: PGConnection -> Bool -> Int32 -> Float -> Time.LocalTime -> Time.UTCTime -> Time.Day -> Time.DiffTime -> SafeString -> [Maybe SafeString] -> Range.Range Int32 -> MyEnum -> PGInet -> Q.Property
+selectProp' pgc b i f t z d p s l r e a = Q.ioProperty $ do
+  [(Just b', Just i', Just f', Just s', Just d', Just t', Just z', Just p', Just l', Just r', Just e', Just a')] <- pgQuery pgc
+    [pgSQL|SELECT ${b}::bool, ${Just i}::int, ${f}::float4, ${getSafeString s}::varchar, ${Just d}::date, ${t}::timestamp, ${z}::timestamptz, ${p}::interval, ${map (fmap getSafeString) l}::text[], ${r}::int4range, ${e}::myenum, ${a}::inet|]
+  return $ Q.conjoin
+    [ i Q.=== i'
+    , b Q.=== b'
+    , getSafeString s Q.=== s'
+    , f Q.=== f'
+    , d Q.=== d'
+    , t Q.=== t'
+    , z Q.=== z'
+    , p Q.=== p'
+    , map (fmap getSafeString) l Q.=== l'
+    , Range.normalize' r Q.=== r'
+    , e Q.=== e'
+    , a Q.=== a'
+    ]
+
+selectFoo :: PGConnection -> [MyFoo] -> Q.Property
+selectFoo pgc l = Q.ioProperty $ do
+  _ <- pgExecute pgc [pgSQL|TRUNCATE myfoo|]
+  let loop [] = return ()
+      loop [x] = do
+        1 <- pgExecute pgc [pgSQL|INSERT INTO myfoo (bar, adé) VALUES (${fooBar x}, ${fooAdé x})|]
+        return ()
+      loop (x:y:r) = do
+        1 <- pgExecute pgc [pgSQL|INSERT INTO myfoo (adé, bar) VALUES (${fooAdé x}, ${fooBar x})|]
+        1 <- pgExecute pgc [pgSQL|$INSERT INTO myfoo (adé, bar) VALUES (${fooAdé y}, ${fooBar y})|]
+        loop r
+  loop l
+  r <- pgQuery pgc [pgSQL|SELECT * FROM myfoo ORDER BY id|]
+  return $ l Q.=== map (\(i,a,b) -> MyFoo i a b) r
+
 tokenProp :: String -> Q.Property
 tokenProp s =
   not (has0 s) Q.==> s Q.=== show (sqlTokens s) where
@@ -135,6 +170,8 @@
 
   r <- Q.quickCheckResult
     $ selectProp c
+    Q..&&. selectProp' c
+    Q..&&. selectFoo c
     Q..&&. tokenProp
     Q..&&. [pgSQL|#abc ${3.14::Float} def $f$ $$ ${1} $f$${2::Int32}|] Q.=== "abc 3.14::real def $f$ $$ ${1} $f$2::integer"
     Q..&&. getQueryString (pgTypeEnv c) ([pgSQL|SELECT ${"ab'cd"::String}::text, ${3.14::Float}::float4|] :: PGSimpleQuery (Maybe String, Maybe Float)) Q.=== "SELECT 'ab''cd'::text, 3.14::float4"
