diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Revision history for influxdb
 
+## v1.4.0 - 2018-03-13
+
+* Implement proper escaping/quoting for queries ([#54](https://github.com/maoe/influxdb-haskell/pull/54))
+* Relax upper version bound for aeson
+* Test against InfluxDB 1.5
+
 ## v1.3.0.1 - 2018-03-06
 
 * Relax upper version bounds for doctest and QuickCheck
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 [![Hackage-Deps](https://img.shields.io/hackage-deps/v/influxdb.svg)](http://packdeps.haskellers.com/feed?needle=influxdb)
 [![Gitter](https://badges.gitter.im/maoe/influxdb-haskell.svg)](https://gitter.im/maoe/influxdb-haskell?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
 
-Currently this library is tested against InfluxDB 1.4.
+Currently this library is tested against InfluxDB 1.5.
 
 ## Getting started
 
diff --git a/influxdb.cabal b/influxdb.cabal
--- a/influxdb.cabal
+++ b/influxdb.cabal
@@ -1,5 +1,5 @@
 name: influxdb
-version: 1.3.0.1
+version: 1.4.0
 synopsis: Haskell client library for InfluxDB
 description:
   @influxdb@ is a Haskell client library for InfluxDB.
@@ -48,6 +48,8 @@
     Database.InfluxDB.Types
     Database.InfluxDB.Write
     Database.InfluxDB.Write.UDP
+  other-modules:
+    Database.InfluxDB.Internal.Text
   other-extensions:
     BangPatterns
     CPP
@@ -72,7 +74,7 @@
   ghc-options: -Wall
   build-depends:
       base >= 4.8 && < 4.12
-    , aeson >= 0.7 && < 1.3
+    , aeson >= 0.7 && < 1.4
     , attoparsec < 0.14
     , bytestring >= 0.10 && < 0.11
     , clock >= 0.7 && < 0.8
diff --git a/src/Database/InfluxDB/Format.hs b/src/Database/InfluxDB/Format.hs
--- a/src/Database/InfluxDB/Format.hs
+++ b/src/Database/InfluxDB/Format.hs
@@ -47,6 +47,7 @@
 import qualified Data.Text.Lazy.Builder.Int as TL
 import qualified Data.Text.Lazy.Builder.RealFloat as TL
 
+import Database.InfluxDB.Internal.Text
 import Database.InfluxDB.Types hiding (database)
 
 -- $setup
@@ -143,46 +144,51 @@
 singleQuote :: T.Text -> TL.Builder
 singleQuote name = "'" <> TL.fromText name <> "'"
 
+identifierBuilder :: T.Text -> TL.Builder
+identifierBuilder = doubleQuote . escapeDoubleQuotes
+
+stringBuilder :: T.Text -> TL.Builder
+stringBuilder = singleQuote . escapeSingleQuotes
+
 -- | Format a database name.
 --
 -- >>> formatQuery ("CREATE DATABASE "%database) "test-db"
 -- "CREATE DATABASE \"test-db\""
 database :: Format r (Database -> r)
-database = makeFormat $ \(Database name) -> doubleQuote name
+database = makeFormat $ \(Database name) -> identifierBuilder name
 
 -- | Format a key (e.g. field names, tag names, tag values etc).
 --
 -- >>> formatQuery ("SELECT "%key%" FROM series") "field"
 -- "SELECT \"field\" FROM series"
+-- >>> formatQuery ("SELECT "%key%" FROM series") "foo\"bar"
+-- "SELECT \"foo\\\"bar\" FROM series"
 key :: Format r (Key -> r)
-key = makeFormat keyBuilder
+key = makeFormat $ \(Key name) -> identifierBuilder name
 
 -- | Format multiple keys.
 --
 -- >>> formatQuery ("SELECT "%keys%" FROM series") ["field1", "field2"]
 -- "SELECT \"field1\",\"field2\" FROM series"
 keys :: Format r ([Key] -> r)
-keys = makeFormat $ mconcat . L.intersperse "," . map keyBuilder
-
-keyBuilder :: Key -> TL.Builder
-keyBuilder (Key name) = doubleQuote name
+keys = makeFormat $
+  mconcat . L.intersperse "," . map (\(Key name) -> identifierBuilder name)
 
 -- | Format a measurement.
 --
 -- >>> formatQuery ("SELECT * FROM "%measurement) "test-series"
 -- "SELECT * FROM \"test-series\""
 measurement :: Format r (Measurement -> r)
-measurement = makeFormat measurementBuilder
+measurement = makeFormat $ \(Measurement name) -> identifierBuilder name
 
 -- | Format a measurement.
 --
 -- >>> formatQuery ("SELECT * FROM "%measurements) ["series1", "series2"]
 -- "SELECT * FROM \"series1\",\"series2\""
 measurements :: Format r ([Measurement] -> r)
-measurements = makeFormat $ mconcat . L.intersperse "," . map measurementBuilder
-
-measurementBuilder :: Measurement -> TL.Builder
-measurementBuilder (Measurement name) = doubleQuote name
+measurements = makeFormat $
+  mconcat . L.intersperse ","
+    . map (\(Measurement name) -> identifierBuilder name)
 
 -- | Format 'QueryField'.
 --
@@ -192,7 +198,7 @@
 field = makeFormat $ \case
   FieldInt n -> TL.decimal n
   FieldFloat d -> TL.realFloat d
-  FieldString s -> singleQuote s
+  FieldString s -> stringBuilder s
   FieldBool b -> if b then "true" else "false"
   FieldNull -> "null"
 
diff --git a/src/Database/InfluxDB/Internal/Text.hs b/src/Database/InfluxDB/Internal/Text.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/InfluxDB/Internal/Text.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Database.InfluxDB.Internal.Text
+  ( escapeCommas
+  , escapeEqualSigns
+  , escapeSpaces
+  , escapeDoubleQuotes
+  , escapeSingleQuotes
+  ) where
+import Data.Text (Text)
+import qualified Data.Text as T
+
+escapeCommas
+  , escapeEqualSigns
+  , escapeSpaces
+  , escapeDoubleQuotes
+  , escapeSingleQuotes :: Text -> Text
+escapeCommas = T.replace "," "\\,"
+escapeEqualSigns = T.replace "=" "\\="
+escapeSpaces = T.replace " " "\\ "
+escapeDoubleQuotes = T.replace "\"" "\\\""
+escapeSingleQuotes = T.replace "'" "\\'"
diff --git a/src/Database/InfluxDB/Line.hs b/src/Database/InfluxDB/Line.hs
--- a/src/Database/InfluxDB/Line.hs
+++ b/src/Database/InfluxDB/Line.hs
@@ -30,9 +30,9 @@
 import qualified Data.ByteString.Builder as B
 import qualified Data.ByteString.Lazy as L
 import qualified Data.Map.Strict as Map
-import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
 
+import Database.InfluxDB.Internal.Text
 import Database.InfluxDB.Types
 
 -- | Placeholder for the Line Protocol
@@ -96,12 +96,6 @@
 
 escapeStringField :: Text -> Text
 escapeStringField = escapeDoubleQuotes
-
-escapeCommas, escapeEqualSigns, escapeSpaces, escapeDoubleQuotes :: Text -> Text
-escapeCommas = T.replace "," "\\,"
-escapeEqualSigns = T.replace "=" "\\="
-escapeSpaces = T.replace " " "\\ "
-escapeDoubleQuotes = T.replace "\"" "\\\""
 
 buildFieldValue :: LineField -> B.Builder
 buildFieldValue = \case
diff --git a/src/Database/InfluxDB/Types.hs b/src/Database/InfluxDB/Types.hs
--- a/src/Database/InfluxDB/Types.hs
+++ b/src/Database/InfluxDB/Types.hs
@@ -116,7 +116,7 @@
 newtype Database = Database { databaseName :: Text } deriving (Eq, Ord)
 
 instance IsString Database where
-  fromString xs = Database $ fromNonEmptyString "Database" xs
+  fromString xs = Database $ identifier "Database" xs
 
 instance Show Database where
   show (Database name) = show name
@@ -128,7 +128,7 @@
 newtype Measurement = Measurement Text deriving (Eq, Ord)
 
 instance IsString Measurement where
-  fromString xs = Measurement $ fromNonEmptyString "Measurement" xs
+  fromString xs = Measurement $ identifier "Measurement" xs
 
 instance Show Measurement where
   show (Measurement name) = show name
@@ -139,14 +139,15 @@
 newtype Key = Key Text deriving (Eq, Ord)
 
 instance IsString Key where
-  fromString xs = Key $ fromNonEmptyString "Key" xs
+  fromString xs = Key $ identifier "Key" xs
 
 instance Show Key where
   show (Key name) = show name
 
-fromNonEmptyString :: String -> String -> Text
-fromNonEmptyString ty xs
+identifier :: String -> String -> Text
+identifier ty xs
   | null xs = error $ ty ++ " should never be empty"
+  | elem '\n' xs = error $ ty ++ " should not contain a new line"
   | otherwise = fromString xs
 
 data Nullability = Nullable | NonNullable deriving Typeable
