{-# LANGUAGE EmptyDataDeriving #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
module Database.InfluxDB.Query
  (
  -- * Query interface
    Query
  , query
  , queryChunked

  -- * Query parameters
  , QueryParams
  , queryParams
  , server
  , database
  , precision
  , manager
  , authentication
  , decoder

  -- * Parsing results
  , QueryResults(..)
  , parseQueryResults
  , parseQueryResultsWith

  -- * Low-level functions
  , withQueryResponse

  -- * Helper types
  , Ignored
  , Empty
  , Tagged(..)
  , untag
  ) where
import Control.Exception
import Control.Monad
import Data.Char
import Data.List
import Data.Maybe (fromMaybe)
import Data.Proxy
import GHC.TypeLits

import Control.Lens
import Data.Aeson
import Data.HashMap.Strict (HashMap)
import Data.Optional (Optional(..), optional)
import Data.Tagged
import Data.Text (Text)
import Data.Vector (Vector)
import Data.Void
import qualified Control.Foldl as L
import qualified Data.Aeson.Parser as A
import qualified Data.Aeson.Types as A
import qualified Data.Attoparsec.ByteString as AB
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Vector as V
import qualified Network.HTTP.Client as HC
import qualified Network.HTTP.Types as HT

import Database.InfluxDB.JSON
import Database.InfluxDB.Types as Types
import qualified Database.InfluxDB.Format as F

-- $setup
-- >>> :set -XDataKinds
-- >>> :set -XOverloadedStrings
-- >>> :set -XRecordWildCards
-- >>> :set -XTypeApplications
-- >>> import Data.Time (UTCTime)
-- >>> import qualified Data.Vector as V
-- >>> import qualified Data.Text as T

-- | Types that can be converted from an JSON object returned by InfluxDB.
--
-- For example the @h2o_feet@ series in
-- [the official document](https://docs.influxdata.com/influxdb/v1.2/query_language/data_exploration/)
-- can be encoded as follows:
--
-- >>> :{
-- data H2OFeet = H2OFeet
--   { time :: UTCTime
--   , levelDesc :: T.Text
--   , location :: T.Text
--   , waterLevel :: Double
--   }
-- instance QueryResults H2OFeet where
--   parseMeasurement prec _name _tags columns fields = do
--     time <- getField "time" columns fields >>= parseUTCTime prec
--     levelDesc <- getField "level_description" columns fields >>= parseJSON
--     location <- getField "location" columns fields >>= parseJSON
--     waterLevel <- getField "water_level" columns fields >>= parseJSON
--     return H2OFeet {..}
-- :}
class QueryResults a where
  -- | Parse a single measurement in a JSON object.
  parseMeasurement
    :: Precision 'QueryRequest
    -- ^ Timestamp precision
    -> Maybe Text
    -- ^ Optional series name
    -> HashMap Text Text
    -- ^ Tag set
    -> Vector Text
    -- ^ Field keys
    -> Array
    -- ^ Field values
    -> A.Parser a

  -- | Always use this 'Decoder' when decoding this type.
  --
  -- @'Just' dec@ means 'decoder' in 'QueryParams' will be ignored and be
  -- replaced with the @dec@. 'Nothing' means 'decoder' in 'QueryParams' will
  -- be used.
  coerceDecoder :: proxy a -> Maybe Decoder
  coerceDecoder proxy a
_ = forall a. Maybe a
Nothing

-- | Parse a JSON object as an array of values of expected type.
parseQueryResults
  :: forall a. QueryResults a
  => Precision 'QueryRequest
  -> Value
  -> A.Parser (Vector a)
parseQueryResults :: forall a.
QueryResults a =>
Precision 'QueryRequest -> Value -> Parser (Vector a)
parseQueryResults =
  forall a.
QueryResults a =>
Decoder -> Precision 'QueryRequest -> Value -> Parser (Vector a)
parseQueryResultsWith forall a b. (a -> b) -> a -> b
$
    forall a. a -> Maybe a -> a
fromMaybe Decoder
strictDecoder (forall a (proxy :: * -> *).
QueryResults a =>
proxy a -> Maybe Decoder
coerceDecoder (forall {k} (t :: k). Proxy t
Proxy :: Proxy a))

parseQueryResultsWith
  :: forall a. QueryResults a
  => Decoder
  -> Precision 'QueryRequest
  -> Value
  -> A.Parser (Vector a)
parseQueryResultsWith :: forall a.
QueryResults a =>
Decoder -> Precision 'QueryRequest -> Value -> Parser (Vector a)
parseQueryResultsWith Decoder
decoder Precision 'QueryRequest
prec =
  forall a.
Decoder
-> (Maybe Text
    -> HashMap Text Text -> Vector Text -> Array -> Parser a)
-> Value
-> Parser (Vector a)
parseResultsWithDecoder
    (forall a. a -> Maybe a -> a
fromMaybe Decoder
decoder (forall a (proxy :: * -> *).
QueryResults a =>
proxy a -> Maybe Decoder
coerceDecoder (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)))
    (forall a.
QueryResults a =>
Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser a
parseMeasurement Precision 'QueryRequest
prec)

-- | 'QueryResults' instance for empty results. Used by
-- 'Database.InfluxDB.Manage.manage'.
--
-- NOTE: This instance is deprecated because it's unclear from the name whether
-- it can be used to ignore results. Use 'Empty' when expecting an empty result.
-- Use 'Ignored' if you want to ignore any results.
instance QueryResults Void where
  parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser Void
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
_ Array
_ = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"parseMeasurement for Void"
  coerceDecoder :: forall (proxy :: * -> *). proxy Void -> Maybe Decoder
coerceDecoder proxy Void
_ = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ (forall a. SomeDecoder a) -> Decoder
Decoder forall a b. (a -> b) -> a -> b
$ SomeDecoder
    { decodeEach :: Parser a -> Parser a
decodeEach = forall a. a -> a
id
    , decodeFold :: Parser (Vector a) -> Parser (Vector a)
decodeFold = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Vector a
V.empty
    }

-- | 'Ignored' can be used in the result type of 'query' when the result values
-- are not needed.
--
-- >>> v <- query @Ignored (queryParams "dummy") "SHOW DATABASES"
-- >>> v
-- []
data Ignored deriving Int -> Ignored -> ShowS
[Ignored] -> ShowS
Ignored -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Ignored] -> ShowS
$cshowList :: [Ignored] -> ShowS
show :: Ignored -> String
$cshow :: Ignored -> String
showsPrec :: Int -> Ignored -> ShowS
$cshowsPrec :: Int -> Ignored -> ShowS
Show

-- | 'QueryResults' instance for ignoring results.
instance QueryResults Ignored where
  parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser Ignored
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
_ Array
_ = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"parseMeasurement for Ignored"
  coerceDecoder :: forall (proxy :: * -> *). proxy Ignored -> Maybe Decoder
coerceDecoder proxy Ignored
_ = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ (forall a. SomeDecoder a) -> Decoder
Decoder forall a b. (a -> b) -> a -> b
$ SomeDecoder
    { decodeEach :: Parser a -> Parser a
decodeEach = forall a. a -> a
id -- doesn't matter
    , decodeFold :: Parser (Vector a) -> Parser (Vector a)
decodeFold = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Vector a
V.empty -- always succeeds with an empty vector
    }

-- | 'Empty' can be used in the result type of 'query' when the expected results
-- are always empty. Note that if the results are not empty, the decoding
-- process will fail:
--
-- >>> let p = queryParams "empty"
-- >>> Database.InfluxDB.Manage.manage p "CREATE DATABASE empty"
-- >>> v <- query @Empty p "SELECT * FROM empty" -- query an empty series
-- >>> v
-- []
data Empty deriving Int -> Empty -> ShowS
[Empty] -> ShowS
Empty -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Empty] -> ShowS
$cshowList :: [Empty] -> ShowS
show :: Empty -> String
$cshow :: Empty -> String
showsPrec :: Int -> Empty -> ShowS
$cshowsPrec :: Int -> Empty -> ShowS
Show

-- | 'QueryResults' instance for empty results. Used by
-- 'Database.InfluxDB.Manage.manage'.
instance QueryResults Empty where
  parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser Empty
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
_ Array
_ = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"parseMeasurement for Empty"
  coerceDecoder :: forall (proxy :: * -> *). proxy Empty -> Maybe Decoder
coerceDecoder proxy Empty
_ = forall a. a -> Maybe a
Just Decoder
strictDecoder -- fail when the results are not empty

fieldName :: KnownSymbol k => proxy k -> T.Text
fieldName :: forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName = String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal

-- | One-off type for non-timestamped measurements
--
-- >>> let p = queryParams "_internal"
-- >>> dbs <- query @(Tagged "name" T.Text) p "SHOW DATABASES"
-- >>> V.find ((== "_internal") . untag) dbs
-- Just (Tagged "_internal")
instance (KnownSymbol k, FromJSON v) => QueryResults (Tagged k v) where
  parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser (Tagged k v)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_name HashMap Text Text
_ Vector Text
columns Array
fields =
    forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k)) Vector Text
columns Array
fields forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. FromJSON a => Value -> Parser a
parseJSON

-- | One-off tuple for sigle-field measurements
instance
  ( KnownSymbol k1, FromJSON v1
  , KnownSymbol k2, FromJSON v2 )
  => QueryResults (Tagged k1 v1, Tagged k2 v2) where
    parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser (Tagged k1 v1, Tagged k2 v2)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
columns Array
fields = do
      Tagged k1 v1
v1 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k1)) Vector Text
columns Array
fields
      Tagged k2 v2
v2 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k2)) Vector Text
columns Array
fields
      forall (m :: * -> *) a. Monad m => a -> m a
return (Tagged k1 v1
v1, Tagged k2 v2
v2)

-- | One-off tuple for two-field measurements
instance
  ( KnownSymbol k1, FromJSON v1
  , KnownSymbol k2, FromJSON v2
  , KnownSymbol k3, FromJSON v3 )
  => QueryResults (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3) where
    parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
columns Array
fields = do
      Tagged k1 v1
v1 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k1)) Vector Text
columns Array
fields
      Tagged k2 v2
v2 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k2)) Vector Text
columns Array
fields
      Tagged k3 v3
v3 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k3)) Vector Text
columns Array
fields
      forall (m :: * -> *) a. Monad m => a -> m a
return (Tagged k1 v1
v1, Tagged k2 v2
v2, Tagged k3 v3
v3)

-- | One-off tuple for three-field measurements
instance
  ( KnownSymbol k1, FromJSON v1
  , KnownSymbol k2, FromJSON v2
  , KnownSymbol k3, FromJSON v3
  , KnownSymbol k4, FromJSON v4 )
  => QueryResults (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4) where
    parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
columns Array
fields = do
      Tagged k1 v1
v1 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k1)) Vector Text
columns Array
fields
      Tagged k2 v2
v2 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k2)) Vector Text
columns Array
fields
      Tagged k3 v3
v3 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k3)) Vector Text
columns Array
fields
      Tagged k4 v4
v4 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k4)) Vector Text
columns Array
fields
      forall (m :: * -> *) a. Monad m => a -> m a
return (Tagged k1 v1
v1, Tagged k2 v2
v2, Tagged k3 v3
v3, Tagged k4 v4
v4)

-- | One-off tuple for four-field measurements
instance
  ( KnownSymbol k1, FromJSON v1
  , KnownSymbol k2, FromJSON v2
  , KnownSymbol k3, FromJSON v3
  , KnownSymbol k4, FromJSON v4
  , KnownSymbol k5, FromJSON v5 )
  => QueryResults
    ( Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4
    , Tagged k5 v5
    ) where
    parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser
     (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4,
      Tagged k5 v5)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
columns Array
fields = do
      Tagged k1 v1
v1 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k1)) Vector Text
columns Array
fields
      Tagged k2 v2
v2 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k2)) Vector Text
columns Array
fields
      Tagged k3 v3
v3 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k3)) Vector Text
columns Array
fields
      Tagged k4 v4
v4 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k4)) Vector Text
columns Array
fields
      Tagged k5 v5
v5 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k5)) Vector Text
columns Array
fields
      forall (m :: * -> *) a. Monad m => a -> m a
return (Tagged k1 v1
v1, Tagged k2 v2
v2, Tagged k3 v3
v3, Tagged k4 v4
v4, Tagged k5 v5
v5)

-- | One-off tuple for five-field measurements
instance
  ( KnownSymbol k1, FromJSON v1
  , KnownSymbol k2, FromJSON v2
  , KnownSymbol k3, FromJSON v3
  , KnownSymbol k4, FromJSON v4
  , KnownSymbol k5, FromJSON v5
  , KnownSymbol k6, FromJSON v6 )
  => QueryResults
    ( Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4
    , Tagged k5 v5, Tagged k6 v6
    ) where
    parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser
     (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4,
      Tagged k5 v5, Tagged k6 v6)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
columns Array
fields = do
      Tagged k1 v1
v1 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k1)) Vector Text
columns Array
fields
      Tagged k2 v2
v2 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k2)) Vector Text
columns Array
fields
      Tagged k3 v3
v3 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k3)) Vector Text
columns Array
fields
      Tagged k4 v4
v4 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k4)) Vector Text
columns Array
fields
      Tagged k5 v5
v5 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k5)) Vector Text
columns Array
fields
      Tagged k6 v6
v6 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k6)) Vector Text
columns Array
fields
      forall (m :: * -> *) a. Monad m => a -> m a
return (Tagged k1 v1
v1, Tagged k2 v2
v2, Tagged k3 v3
v3, Tagged k4 v4
v4, Tagged k5 v5
v5, Tagged k6 v6
v6)

-- | One-off tuple for six-field measurement
instance
  ( KnownSymbol k1, FromJSON v1
  , KnownSymbol k2, FromJSON v2
  , KnownSymbol k3, FromJSON v3
  , KnownSymbol k4, FromJSON v4
  , KnownSymbol k5, FromJSON v5
  , KnownSymbol k6, FromJSON v6
  , KnownSymbol k7, FromJSON v7 )
  => QueryResults
    ( Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4
    , Tagged k5 v5, Tagged k6 v6, Tagged k7 v7
    ) where
    parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser
     (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4,
      Tagged k5 v5, Tagged k6 v6, Tagged k7 v7)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
columns Array
fields = do
      Tagged k1 v1
v1 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k1)) Vector Text
columns Array
fields
      Tagged k2 v2
v2 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k2)) Vector Text
columns Array
fields
      Tagged k3 v3
v3 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k3)) Vector Text
columns Array
fields
      Tagged k4 v4
v4 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k4)) Vector Text
columns Array
fields
      Tagged k5 v5
v5 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k5)) Vector Text
columns Array
fields
      Tagged k6 v6
v6 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k6)) Vector Text
columns Array
fields
      Tagged k7 v7
v7 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k7)) Vector Text
columns Array
fields
      forall (m :: * -> *) a. Monad m => a -> m a
return (Tagged k1 v1
v1, Tagged k2 v2
v2, Tagged k3 v3
v3, Tagged k4 v4
v4, Tagged k5 v5
v5, Tagged k6 v6
v6, Tagged k7 v7
v7)

-- | One-off tuple for seven-field measurements
instance
  ( KnownSymbol k1, FromJSON v1
  , KnownSymbol k2, FromJSON v2
  , KnownSymbol k3, FromJSON v3
  , KnownSymbol k4, FromJSON v4
  , KnownSymbol k5, FromJSON v5
  , KnownSymbol k6, FromJSON v6
  , KnownSymbol k7, FromJSON v7
  , KnownSymbol k8, FromJSON v8 )
  => QueryResults
    ( Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4
    , Tagged k5 v5, Tagged k6 v6, Tagged k7 v7, Tagged k8 v8
    ) where
    parseMeasurement :: Precision 'QueryRequest
-> Maybe Text
-> HashMap Text Text
-> Vector Text
-> Array
-> Parser
     (Tagged k1 v1, Tagged k2 v2, Tagged k3 v3, Tagged k4 v4,
      Tagged k5 v5, Tagged k6 v6, Tagged k7 v7, Tagged k8 v8)
parseMeasurement Precision 'QueryRequest
_ Maybe Text
_ HashMap Text Text
_ Vector Text
columns Array
fields = do
      Tagged k1 v1
v1 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k1)) Vector Text
columns Array
fields
      Tagged k2 v2
v2 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k2)) Vector Text
columns Array
fields
      Tagged k3 v3
v3 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k3)) Vector Text
columns Array
fields
      Tagged k4 v4
v4 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k4)) Vector Text
columns Array
fields
      Tagged k5 v5
v5 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k5)) Vector Text
columns Array
fields
      Tagged k6 v6
v6 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k6)) Vector Text
columns Array
fields
      Tagged k7 v7
v7 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k7)) Vector Text
columns Array
fields
      Tagged k8 v8
v8 <- forall a. FromJSON a => Value -> Parser a
parseJSON
        forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *).
MonadFail m =>
Text -> Vector Text -> Array -> m Value
getField (forall (k :: Symbol) (proxy :: Symbol -> *).
KnownSymbol k =>
proxy k -> Text
fieldName (forall {k} (t :: k). Proxy t
Proxy :: Proxy k8)) Vector Text
columns Array
fields
      forall (m :: * -> *) a. Monad m => a -> m a
return (Tagged k1 v1
v1, Tagged k2 v2
v2, Tagged k3 v3
v3, Tagged k4 v4
v4, Tagged k5 v5
v5, Tagged k6 v6
v6, Tagged k7 v7
v7, Tagged k8 v8
v8)

-- | The full set of parameters for the query API
--
-- Following lenses are available to access its fields:
--
-- * 'server'
-- * 'database'
-- * 'precision'
-- * 'manager'
-- * 'authentication'
-- * 'decoder'
data QueryParams = QueryParams
  { QueryParams -> Server
queryServer :: !Server
  , QueryParams -> Database
queryDatabase :: !Database
  , QueryParams -> Precision 'QueryRequest
queryPrecision :: !(Precision 'QueryRequest)
  -- ^ Timestamp precision
  --
  -- InfluxDB uses nanosecond precision if nothing is specified.
  , QueryParams -> Maybe Credentials
queryAuthentication :: !(Maybe Credentials)
  -- ^ No authentication by default
  , QueryParams -> Either ManagerSettings Manager
queryManager :: !(Either HC.ManagerSettings HC.Manager)
  -- ^ HTTP connection manager
  , QueryParams -> Decoder
queryDecoder :: Decoder
  -- ^ Decoder settings to configure how to parse a JSON resposne given a row
  -- parser
  }

-- | Smart constructor for 'QueryParams'
--
-- Default parameters:
--
--   ['server'] 'defaultServer'
--   ['precision'] 'RFC3339'
--   ['authentication'] 'Nothing'
--   ['manager'] @'Left' 'HC.defaultManagerSettings'@
--   ['decoder'] @'strictDecoder'@
queryParams :: Database -> QueryParams
queryParams :: Database -> QueryParams
queryParams Database
queryDatabase = QueryParams
  { queryServer :: Server
queryServer = Server
defaultServer
  , queryPrecision :: Precision 'QueryRequest
queryPrecision = Precision 'QueryRequest
RFC3339
  , queryAuthentication :: Maybe Credentials
queryAuthentication = forall a. Maybe a
Nothing
  , queryManager :: Either ManagerSettings Manager
queryManager = forall a b. a -> Either a b
Left ManagerSettings
HC.defaultManagerSettings
  , queryDecoder :: Decoder
queryDecoder = Decoder
strictDecoder
  , Database
queryDatabase :: Database
queryDatabase :: Database
..
  }

-- | Query data from InfluxDB.
--
-- It may throw 'InfluxException'.
--
-- If you need a lower-level interface (e.g. to bypass the 'QueryResults'
-- constraint etc), see 'withQueryResponse'.
query :: forall a. QueryResults a => QueryParams -> Query -> IO (Vector a)
query :: forall a. QueryResults a => QueryParams -> Query -> IO (Vector a)
query QueryParams
params Query
q = forall r.
QueryParams
-> Maybe (Optional Int)
-> Query
-> (Request -> Response BodyReader -> IO r)
-> IO r
withQueryResponse QueryParams
params forall a. Maybe a
Nothing Query
q Request -> Response BodyReader -> IO (Vector a)
go
  where
    go :: Request -> Response BodyReader -> IO (Vector a)
go Request
request Response BodyReader
response = do
      [Method]
chunks <- BodyReader -> IO [Method]
HC.brConsume forall a b. (a -> b) -> a -> b
$ forall body. Response body -> body
HC.responseBody Response BodyReader
response
      let body :: ByteString
body = [Method] -> ByteString
BL.fromChunks [Method]
chunks
      case forall a. FromJSON a => ByteString -> Either String a
eitherDecode' ByteString
body of
        Left String
message -> forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ String -> Request -> ByteString -> InfluxException
UnexpectedResponse String
message Request
request ByteString
body
        Right Value
val -> do
          let parser :: Value -> Parser (Vector a)
parser = forall a.
QueryResults a =>
Decoder -> Precision 'QueryRequest -> Value -> Parser (Vector a)
parseQueryResultsWith
                (forall a. a -> Maybe a -> a
fromMaybe
                  (QueryParams -> Decoder
queryDecoder QueryParams
params)
                  (forall a (proxy :: * -> *).
QueryResults a =>
proxy a -> Maybe Decoder
coerceDecoder (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)))
                (QueryParams -> Precision 'QueryRequest
queryPrecision QueryParams
params)
          case forall a b. (a -> Parser b) -> a -> Result b
A.parse Value -> Parser (Vector a)
parser Value
val of
            A.Success Vector a
vec -> forall (m :: * -> *) a. Monad m => a -> m a
return Vector a
vec
            A.Error String
message -> forall body a. String -> Request -> Response body -> Value -> IO a
errorQuery String
message Request
request Response BodyReader
response Value
val

setPrecision
  :: Precision 'QueryRequest
  -> [(B.ByteString, Maybe B.ByteString)]
  -> [(B.ByteString, Maybe B.ByteString)]
setPrecision :: Precision 'QueryRequest
-> [(Method, Maybe Method)] -> [(Method, Maybe Method)]
setPrecision Precision 'QueryRequest
prec [(Method, Maybe Method)]
qs = forall b a. b -> (a -> b) -> Maybe a -> b
maybe [(Method, Maybe Method)]
qs (\Method
p -> (Method
"epoch", forall a. a -> Maybe a
Just Method
p)forall a. a -> [a] -> [a]
:[(Method, Maybe Method)]
qs) forall a b. (a -> b) -> a -> b
$
  Precision 'QueryRequest -> Maybe Method
precisionParam Precision 'QueryRequest
prec

precisionParam :: Precision 'QueryRequest -> Maybe B.ByteString
precisionParam :: Precision 'QueryRequest -> Maybe Method
precisionParam = \case
  Precision 'QueryRequest
Nanosecond -> forall (m :: * -> *) a. Monad m => a -> m a
return Method
"ns"
  Precision 'QueryRequest
Microsecond -> forall (m :: * -> *) a. Monad m => a -> m a
return Method
"u"
  Precision 'QueryRequest
Millisecond -> forall (m :: * -> *) a. Monad m => a -> m a
return Method
"ms"
  Precision 'QueryRequest
Second -> forall (m :: * -> *) a. Monad m => a -> m a
return Method
"s"
  Precision 'QueryRequest
Minute -> forall (m :: * -> *) a. Monad m => a -> m a
return Method
"m"
  Precision 'QueryRequest
Hour -> forall (m :: * -> *) a. Monad m => a -> m a
return Method
"h"
  Precision 'QueryRequest
RFC3339 -> forall a. Maybe a
Nothing

-- | Same as 'query' but it instructs InfluxDB to stream chunked responses
-- rather than returning a huge JSON object. This can be lot more efficient than
-- 'query' if the result is huge.
--
-- It may throw 'InfluxException'.
--
-- If you need a lower-level interface (e.g. to bypass the 'QueryResults'
-- constraint etc), see 'withQueryResponse'.
queryChunked
  :: QueryResults a
  => QueryParams
  -> Optional Int
  -- ^ Chunk size
  --
  -- By 'Default', InfluxDB chunks responses by series or by every 10,000
  -- points, whichever occurs first. If it set to a 'Specific' value, InfluxDB
  -- chunks responses by series or by that number of points.
  -> Query
  -> L.FoldM IO (Vector a) r
  -> IO r
queryChunked :: forall a r.
QueryResults a =>
QueryParams
-> Optional Int -> Query -> FoldM IO (Vector a) r -> IO r
queryChunked QueryParams
params Optional Int
chunkSize Query
q (L.FoldM x -> Vector a -> IO x
step IO x
initialize x -> IO r
extract) =
  forall r.
QueryParams
-> Maybe (Optional Int)
-> Query
-> (Request -> Response BodyReader -> IO r)
-> IO r
withQueryResponse QueryParams
params (forall a. a -> Maybe a
Just Optional Int
chunkSize) Query
q Request -> Response BodyReader -> IO r
go
  where
    go :: Request -> Response BodyReader -> IO r
go Request
request Response BodyReader
response = do
      x
x0 <- IO x
initialize
      Method
chunk0 <- forall body. Response body -> body
HC.responseBody Response BodyReader
response
      x
x <- x -> (Method -> IResult Method Value) -> Method -> IO x
loop x
x0 Method -> IResult Method Value
k0 Method
chunk0
      x -> IO r
extract x
x
      where
        k0 :: Method -> IResult Method Value
k0 = forall a. Parser a -> Method -> Result a
AB.parse Parser Value
A.json
        loop :: x -> (Method -> IResult Method Value) -> Method -> IO x
loop x
x Method -> IResult Method Value
k Method
chunk
          | Method -> Bool
B.null Method
chunk = forall (m :: * -> *) a. Monad m => a -> m a
return x
x
          | Bool
otherwise = case Method -> IResult Method Value
k Method
chunk of
            AB.Fail Method
unconsumed [String]
_contexts String
message ->
              forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ String -> Request -> ByteString -> InfluxException
UnexpectedResponse String
message Request
request forall a b. (a -> b) -> a -> b
$
                Method -> ByteString
BL.fromStrict Method
unconsumed
            AB.Partial Method -> IResult Method Value
k' -> do
              Method
chunk' <- forall body. Response body -> body
HC.responseBody Response BodyReader
response
              x -> (Method -> IResult Method Value) -> Method -> IO x
loop x
x Method -> IResult Method Value
k' Method
chunk'
            AB.Done Method
leftover Value
val ->
              case forall a b. (a -> Parser b) -> a -> Result b
A.parse (forall a.
QueryResults a =>
Precision 'QueryRequest -> Value -> Parser (Vector a)
parseQueryResults (QueryParams -> Precision 'QueryRequest
queryPrecision QueryParams
params)) Value
val of
                A.Success Vector a
vec -> do
                  x
x' <- x -> Vector a -> IO x
step x
x Vector a
vec
                  x -> (Method -> IResult Method Value) -> Method -> IO x
loop x
x' Method -> IResult Method Value
k0 Method
leftover
                A.Error String
message -> forall body a. String -> Request -> Response body -> Value -> IO a
errorQuery String
message Request
request Response BodyReader
response Value
val

-- | Lower-level interface to query data.
withQueryResponse
  :: QueryParams
  -> Maybe (Optional Int)
  -- ^ Chunk size
  --
  -- By 'Nothing', InfluxDB returns all matching data points at once.
  -- By @'Just' 'Default'@, InfluxDB chunks responses by series or by every
  -- 10,000 points, whichever occurs first. If it set to a 'Specific' value,
  -- InfluxDB chunks responses by series or by that number of points.
  -> Query
  -> (HC.Request -> HC.Response HC.BodyReader -> IO r)
  -> IO r
withQueryResponse :: forall r.
QueryParams
-> Maybe (Optional Int)
-> Query
-> (Request -> Response BodyReader -> IO r)
-> IO r
withQueryResponse QueryParams
params Maybe (Optional Int)
chunkSize Query
q Request -> Response BodyReader -> IO r
f = do
    Manager
manager' <- forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ManagerSettings -> IO Manager
HC.newManager forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ QueryParams -> Either ManagerSettings Manager
queryManager QueryParams
params
    forall a.
Request -> Manager -> (Response BodyReader -> IO a) -> IO a
HC.withResponse Request
request Manager
manager' (Request -> Response BodyReader -> IO r
f Request
request)
      forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` (forall e a. Exception e => e -> IO a
throwIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. HttpException -> InfluxException
HTTPException)
  where
    request :: Request
request =
      [(Method, Maybe Method)] -> Request -> Request
HC.setQueryString (Precision 'QueryRequest
-> [(Method, Maybe Method)] -> [(Method, Maybe Method)]
setPrecision (QueryParams -> Precision 'QueryRequest
queryPrecision QueryParams
params) [(Method, Maybe Method)]
queryString) forall a b. (a -> b) -> a -> b
$
        QueryParams -> Request
queryRequest QueryParams
params
    queryString :: [(Method, Maybe Method)]
queryString = [(Method, Maybe Method)] -> [(Method, Maybe Method)]
addChunkedParam
      [ (Method
"q", forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Query -> Method
F.fromQuery Query
q)
      , (Method
"db", forall a. a -> Maybe a
Just Method
db)
      ]
      where
        !db :: Method
db = Text -> Method
TE.encodeUtf8 forall a b. (a -> b) -> a -> b
$ Database -> Text
databaseName forall a b. (a -> b) -> a -> b
$ QueryParams -> Database
queryDatabase QueryParams
params
    addChunkedParam :: [(Method, Maybe Method)] -> [(Method, Maybe Method)]
addChunkedParam [(Method, Maybe Method)]
ps = case Maybe (Optional Int)
chunkSize of
      Maybe (Optional Int)
Nothing -> [(Method, Maybe Method)]
ps
      Just Optional Int
size ->
        let !chunked :: Method
chunked = forall b a. b -> (a -> b) -> Optional a -> b
optional Method
"true" (Int -> Method
decodeChunkSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> a -> a
max Int
1) Optional Int
size
        in (Method
"chunked", forall a. a -> Maybe a
Just Method
chunked) forall a. a -> [a] -> [a]
: [(Method, Maybe Method)]
ps
      where
        decodeChunkSize :: Int -> Method
decodeChunkSize = ByteString -> Method
BL.toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
BB.toLazyByteString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder
BB.intDec


queryRequest :: QueryParams -> HC.Request
queryRequest :: QueryParams -> Request
queryRequest QueryParams {Maybe Credentials
Either ManagerSettings Manager
Server
Precision 'QueryRequest
Database
Decoder
queryDecoder :: Decoder
queryManager :: Either ManagerSettings Manager
queryAuthentication :: Maybe Credentials
queryPrecision :: Precision 'QueryRequest
queryDatabase :: Database
queryServer :: Server
queryDecoder :: QueryParams -> Decoder
queryManager :: QueryParams -> Either ManagerSettings Manager
queryAuthentication :: QueryParams -> Maybe Credentials
queryPrecision :: QueryParams -> Precision 'QueryRequest
queryDatabase :: QueryParams -> Database
queryServer :: QueryParams -> Server
..} = Request -> Request
applyBasicAuth forall a b. (a -> b) -> a -> b
$ Request
HC.defaultRequest
  { host :: Method
HC.host = Text -> Method
TE.encodeUtf8 Text
_host
  , port :: Int
HC.port = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
_port
  , secure :: Bool
HC.secure = Bool
_ssl
  , method :: Method
HC.method = Method
"GET"
  , path :: Method
HC.path = Method
"/query"
  }
  where
    Server {Bool
Int
Text
_ssl :: Server -> Bool
_port :: Server -> Int
_host :: Server -> Text
_ssl :: Bool
_port :: Int
_host :: Text
..} = Server
queryServer
    applyBasicAuth :: Request -> Request
applyBasicAuth =
      case Maybe Credentials
queryAuthentication of
        Maybe Credentials
Nothing -> forall a. a -> a
id
        Just Credentials {Text
_password :: Credentials -> Text
_user :: Credentials -> Text
_password :: Text
_user :: Text
..} ->
          Method -> Method -> Request -> Request
HC.applyBasicAuth (Text -> Method
TE.encodeUtf8 Text
_user) (Text -> Method
TE.encodeUtf8 Text
_password)

errorQuery :: String -> HC.Request -> HC.Response body -> A.Value -> IO a
errorQuery :: forall body a. String -> Request -> Response body -> Value -> IO a
errorQuery String
message Request
request Response body
response Value
val = do
  let status :: Status
status = forall body. Response body -> Status
HC.responseStatus Response body
response
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Status -> Bool
HT.statusIsServerError Status
status) forall a b. (a -> b) -> a -> b
$
    forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ String -> InfluxException
ServerError String
message
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Status -> Bool
HT.statusIsClientError Status
status) forall a b. (a -> b) -> a -> b
$
    forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ String -> Request -> InfluxException
ClientError String
message Request
request
  forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ String -> Request -> ByteString -> InfluxException
UnexpectedResponse
    (String
"BUG: " forall a. [a] -> [a] -> [a]
++ String
message forall a. [a] -> [a] -> [a]
++ String
" in Database.InfluxDB.Query.query")
    Request
request
    (forall a. ToJSON a => a -> ByteString
encode Value
val)

makeLensesWith
  ( lensRules
    & lensField .~ mappingNamer
      (\name -> case stripPrefix "query" name of
        Just (c:cs) -> ['_':toLower c:cs]
        _ -> [])
    )
  ''QueryParams

-- |
-- >>> let p = queryParams "foo"
-- >>> p ^. server.host
-- "localhost"
instance HasServer QueryParams where
  server :: Lens' QueryParams Server
server = Lens' QueryParams Server
_server

-- |
-- >>> let p = queryParams "foo"
-- >>> p ^. database
-- "foo"
instance HasDatabase QueryParams where
  database :: Lens' QueryParams Database
database = Lens' QueryParams Database
_database

-- | Returning JSON responses contain timestamps in the specified
-- precision/format.
--
-- >>> let p = queryParams "foo"
-- >>> p ^. precision
-- RFC3339
instance HasPrecision 'QueryRequest QueryParams where
  precision :: Lens' QueryParams (Precision 'QueryRequest)
precision = Lens' QueryParams (Precision 'QueryRequest)
_precision

-- |
-- >>> let p = queryParams "foo" & manager .~ Left HC.defaultManagerSettings
instance HasManager QueryParams where
  manager :: Lens' QueryParams (Either ManagerSettings Manager)
manager = Lens' QueryParams (Either ManagerSettings Manager)
_manager

-- | Authentication info for the query
--
-- >>> let p = queryParams "foo"
-- >>> p ^. authentication
-- Nothing
-- >>> let p' = p & authentication ?~ credentials "john" "passw0rd"
-- >>> p' ^. authentication.traverse.user
-- "john"
instance HasCredentials QueryParams where
  authentication :: Lens' QueryParams (Maybe Credentials)
authentication = Lens' QueryParams (Maybe Credentials)
_authentication

-- | Decoder settings
--
-- >>> let p = queryParams "foo"
-- >>> let _ = p & decoder .~ strictDecoder
-- >>> let _ = p & decoder .~ lenientDecoder
decoder :: Lens' QueryParams Decoder
decoder :: Lens' QueryParams Decoder
decoder = Lens' QueryParams Decoder
_decoder