cql-io 1.0.1 → 1.0.1.1
raw patch · 6 files changed
+112/−34 lines, 6 filessetup-changedPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Database.CQL.IO: Identity :: a -> Identity a
+ Database.CQL.IO: [runIdentity] :: Identity a -> a
+ Database.CQL.IO: newtype Identity a
- Database.CQL.IO: Authenticator :: !AuthMechanism -> (AuthContext -> IO (AuthResponse, s)) -> Maybe (s -> AuthChallenge -> IO (AuthResponse, s)) -> (s -> AuthSuccess -> IO ()) -> Authenticator
+ Database.CQL.IO: Authenticator :: !AuthMechanism -> AuthContext -> IO (AuthResponse, s) -> Maybe (s -> AuthChallenge -> IO (AuthResponse, s)) -> s -> AuthSuccess -> IO () -> Authenticator
- Database.CQL.IO: Policy :: ([Host] -> [Host] -> IO ()) -> (HostEvent -> IO ()) -> IO (Maybe Host) -> IO [Host] -> (Host -> IO Bool) -> IO Word -> IO String -> Policy
+ Database.CQL.IO: Policy :: [Host] -> [Host] -> IO () -> HostEvent -> IO () -> IO (Maybe Host) -> IO [Host] -> Host -> IO Bool -> IO Word -> IO String -> Policy
- Database.CQL.IO: data Consistency :: *
+ Database.CQL.IO: data Consistency
- Database.CQL.IO: data QueryParams a :: * -> *
+ Database.CQL.IO: data QueryParams a
- Database.CQL.IO: data R :: *
+ Database.CQL.IO: data R
- Database.CQL.IO: data Row :: *
+ Database.CQL.IO: data Row
- Database.CQL.IO: data S :: *
+ Database.CQL.IO: data S
- Database.CQL.IO: data SerialConsistency :: *
+ Database.CQL.IO: data SerialConsistency
- Database.CQL.IO: data W :: *
+ Database.CQL.IO: data W
- Database.CQL.IO: newtype QueryString k a b :: * -> * -> * -> *
+ Database.CQL.IO: newtype QueryString k a b
Files
- CHANGELOG +4/−0
- Setup.hs +2/−0
- cql-io.cabal +1/−1
- src/Database/CQL/IO.hs +63/−31
- src/Database/CQL/IO/PrepQuery.hs +41/−2
- src/Database/CQL/IO/Settings.hs +1/−0
CHANGELOG view
@@ -1,3 +1,7 @@+1.0.1.1+-------+- Add more documentation on queries.+ 1.0.1 ------ - Address an issue whereby Cassandra 'Error' responses might be mistakenly
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
cql-io.cabal view
@@ -1,5 +1,5 @@ name: cql-io-version: 1.0.1+version: 1.0.1.1 synopsis: Cassandra CQL client. license: MPL-2.0 license-file: LICENSE
src/Database/CQL/IO.hs view
@@ -24,32 +24,6 @@ -- > shutdown c -- @ -------- __Note on prepared statements__------ Prepared statements are fully supported but imply certain--- complexities which lead to some assumptions beyond the scope--- of the CQL binary protocol specification (spec):------ (1) The spec scopes the 'QueryId' to the node the query has--- been prepared with. The spec does not state anything--- about the format of the 'QueryId', however it seems that--- at least the official Java driver assumes that any given--- 'QueryString' yields the same 'QueryId' on every node.--- We make the same assumption.--- (2) In case a node does not know a given 'QueryId' an 'Unprepared'--- error is returned. We assume that it is always safe to then--- transparently re-prepare the corresponding 'QueryString' and--- to re-execute the original request against the same node.------ Besides these assumptions there is also a potential tradeoff in--- regards to /eager/ vs. /lazy/ query preparation.--- We understand /eager/ to mean preparation against all current nodes of--- a cluster and /lazy/ to mean preparation against a single node if--- required, i.e. after an 'Unprepared' error response. Which strategy to--- choose depends on the scope of query reuse and the size of the cluster.--- The global default can be changed through the 'Settings' module and per--- action using 'withPrepareStrategy'. {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE LambdaCase #-}@@ -127,14 +101,16 @@ , debugInfo -- * Queries+ -- $queries , R, W, S , QueryParams (..) , defQueryParams , Consistency (..) , SerialConsistency (..)- , QueryString (..)+ , Identity (..) -- ** Basic Queries+ , QueryString (..) , query , query1 , write@@ -169,10 +145,7 @@ , once -- ** Low-Level Queries- --- -- | Note: Use of these low-level functions may require additional imports from- -- @Database.CQL.Protocol@ or its submodules in order to construct- -- 'Request's and evaluate 'Response's.+ -- $low-level-queries , RunQ (..) , request @@ -189,6 +162,7 @@ import Control.Applicative import Control.Monad.Catch+import Data.Functor.Identity import Data.Maybe (isJust, listToMaybe) import Database.CQL.Protocol import Database.CQL.IO.Batch hiding (batch)@@ -202,6 +176,64 @@ import Prelude hiding (init) import qualified Database.CQL.IO.Batch as B++-- $queries+--+-- Queries are defined either as 'QueryString's or 'PrepQuery's.+-- Both types carry three phantom type parameters used to describe+-- the query, input and output types, respectively, as follows:+--+-- * @__k__@ is one of 'R'ead, 'W'rite or 'S'chema.+-- * @__a__@ is the tuple type for the input, i.e. for the+-- parameters bound by positional (@?@) or named (@:foo@) placeholders.+-- * @__b__@ is the tuple type for the outputs, i.e. for the+-- columns selected in a query.+--+-- Thereby every type used in an input or output tuple must be an instance+-- of the 'Cql' typeclass. It is the responsibility of user code+-- that the type ascription of a query matches the order, number and types of+-- the parameters. For example:+--+-- @+-- myQuery :: QueryString R (Identity UUID) (Text, Int, Maybe UTCTime)+-- myQuery = "select name, age, birthday from user where id = ?"+-- @+--+-- In this example, the query is declared as a 'R'ead with a single+-- input (id) and three outputs (name, age and birthday).+--+-- Note that a single input or output type needs to be wrapped+-- in the 'Identity' newtype, for which there is a `Cql` instance,+-- in order to avoid overlapping instances.+--+-- It is a common strategy to use additional @newtype@s with derived+-- @Cql@ instances for additional type safety, e.g.+--+-- @+-- newtype UserId = UserId UUID deriving (Eq, Show, Cql)+-- @+--+-- The input and output tuples can further be automatically+-- converted from and to records via the 'Database.CQL.Protocol.Record'+-- typeclass, whose instances can be generated via @TemplateHaskell@,+-- if desired.+--+-- __Note on null values__+--+-- In principle, any column in Cassandra is /nullable/, i.e. may be+-- be set to @null@ as a result of row operations. It is therefore+-- important that any output type of a query that may be null+-- is wrapped in the 'Maybe' type constructor.+-- It is a common pitfall that a column is assumed to never contain+-- null values, when in fact partial updates or deletions on a row,+-- including via the use of TTLs, may result in null values and thus+-- runtime errors when processing the responses.++-- $low-level-queries+--+-- /Note/: Use of the these functions may require additional imports from+-- @Database.CQL.Protocol@ or its submodules in order to construct+-- 'Request's and evaluate 'Response's. -- | A type which can be run as a query. class RunQ q where
src/Database/CQL/IO/PrepQuery.hs view
@@ -35,8 +35,47 @@ ----------------------------------------------------------------------------- -- Prepared Query --- | Representation of a prepared query.--- Actual preparation is handled transparently by the driver.+-- | Representation of a prepared 'QueryString'. A prepared query is+-- executed in two stages:+--+-- 1. The query string is sent to a server without parameters for+-- preparation. The server responds with a 'QueryId'.+-- 2. The prepared query is executed by sending the 'QueryId'+-- and parameters to the server.+--+-- Thereby step 1 is only performed when the query has not yet been prepared+-- with the host (coordinator) used for query execution. Thus, prepared+-- queries enhance performance by avoiding the repeated sending and parsing+-- of query strings.+--+-- Query preparation is handled transparently by the client.+-- See 'Database.CQL.IO.setPrepareStrategy'.+--+-- __Note__+--+-- Prepared statements are fully supported but rely on some+-- assumptions beyond the scope of the CQL binary protocol+-- specification (spec):+--+-- (1) The spec scopes the 'QueryId' to the node the query has+-- been prepared with. The spec does not state anything+-- about the format of the 'QueryId'. However the official+-- Java driver assumes that any given 'QueryString' yields+-- the same 'QueryId' on every node. This client make the+-- same assumption.+-- (2) In case a node does not know a given 'QueryId' an 'Unprepared'+-- error is returned. We assume that it is always safe to+-- transparently re-prepare the corresponding 'QueryString' and+-- to re-execute the original request against the same node.+--+-- Besides these assumptions there is also a potential tradeoff in+-- regards to /eager/ vs. /lazy/ query preparation.+-- We understand /eager/ to mean preparation against all current nodes of+-- a cluster and /lazy/ to mean preparation against a single node on demand,+-- i.e. upon receiving an 'Unprepared' error response. Which strategy to+-- choose depends on the scope of query reuse and the size of the cluster.+-- The global default can be changed through the 'Settings' module as well+-- as locally using 'withPrepareStrategy'. data PrepQuery k a b = PrepQuery { pqStr :: !(QueryString k a b) , pqId :: !PrepQueryId
src/Database/CQL/IO/Settings.hs view
@@ -25,6 +25,7 @@ import qualified Data.HashMap.Strict as HashMap +-- | Strategy for the execution of 'PrepQuery's. data PrepareStrategy = EagerPrepare -- ^ cluster-wide preparation | LazyPrepare -- ^ on-demand per node preparation