| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Hmssql.Query.Internal
Description
What Hmssql.Query and Hmssql.BatchQuery share beyond the types of
Hmssql.Query.Types: encoding a query into its sp_executesql call,
reading a response step by step, decoding result sets from a reader, and
packing statements into messages. Applications use Hmssql.Query,
which re-exports readStep, drainResponse and paramNameProblem;
nothing here is stable.
Synopsis
- executeSqlRpc :: Text -> [(Text, EncodedParam)] -> RpcRequest
- textParam :: Text -> RpcParam
- declarationParam :: [(Text, EncodedParam)] -> RpcParam
- valueParams :: [(Text, EncodedParam)] -> [RpcParam]
- encodeQuery :: TdsContext -> Query -> Either String (Text, [(Text, EncodedParam)])
- encodeQueryParams :: TdsContext -> [QueryParam] -> Either String [(Text, EncodedParam)]
- positionalName :: Int -> Text
- reservedNameProblem :: Text -> Maybe String
- paramNameProblem :: Text -> Maybe String
- readStep :: ResponseReader -> RowRead r -> IO (ResponseStep r)
- readStepReversed :: ResponseReader -> RowRead r -> IO (ResponseStep r)
- readStepUsing :: Bool -> ResponseReader -> RowRead r -> IO (ResponseStep r)
- ignoreRows :: RowRead ()
- drainResponse :: ResponseReader -> IO ()
- yieldRows :: ResponseReader -> [r] -> Stream (Of r) IO () -> Stream (Of r) IO ()
- type RowCompiler r = TdsContext -> [ColumnInfo] -> Either DecodeError (CompiledRow r)
- compilerFor :: RowDecoder r -> RowCompiler r
- compilerForM :: RowDecoderMonadic r -> RowCompiler r
- sqlRowCompiler :: RowCompiler SqlRow
- firstResultSet :: RowCompiler r -> ResponseReader -> IO (Maybe (RowRead r))
- endsResultSet :: Token -> Bool
- foldFirstResultSet :: RowCompiler r -> ResponseReader -> a -> (a -> r -> IO a) -> IO a
- foldBatches :: RowCompiler r -> ResponseReader -> a -> (a -> [r] -> IO a) -> IO a
- foldBatchesUsing :: (ResponseReader -> RowRead r -> IO (ResponseStep r)) -> RowCompiler r -> ResponseReader -> a -> (a -> [r] -> IO a) -> IO a
- readFirstResultSet :: RowCompiler r -> ResponseReader -> IO [r]
- newtype ReversedBatch r = ReversedBatch [r]
- joinReversedBatches :: [ReversedBatch r] -> [r]
- streamFirstResultSet :: RowCompiler r -> ResponseReader -> IO () -> Stream (Of r) IO ()
- type StatementEncoder s a = TdsContext -> s -> a -> Either String (Text, RpcRequest, s)
- queryStatement :: StatementEncoder () Query
- statementsRequest :: [(Text, RpcRequest)] -> IO Request
- statementMessageBytes :: Int
- takeStatements :: StatementEncoder s a -> TdsContext -> s -> Int -> [a] -> Either String ([(Text, RpcRequest)], Int, [a], s)
- joinBatches :: [[r]] -> [r]
- exactlyOne :: [r] -> IO r
- atMostOne :: [r] -> IO (Maybe r)
- readResultSets :: RowCompiler r -> ResponseReader -> IO [ResultSet r]
- readResultSetsWith :: ResultSets a -> ResponseReader -> IO a
Documentation
executeSqlRpc :: Text -> [(Text, EncodedParam)] -> RpcRequest Source #
The sp_executesql call of a statement with its parameters named.
textParam :: Text -> RpcParam Source #
An nvarchar(max) parameter of sp_executesql's own: the statement,
or the declaration.
declarationParam :: [(Text, EncodedParam)] -> RpcParam Source #
@params: the parameters' names and types, @p1 int,@p2
nvarchar(4000), written as UTF-16LE straight into one buffer.
valueParams :: [(Text, EncodedParam)] -> [RpcParam] Source #
encodeQuery :: TdsContext -> Query -> Either String (Text, [(Text, EncodedParam)]) Source #
A query's text and its parameters, encoded, checked and named, or why it can't be sent.
encodeQueryParams :: TdsContext -> [QueryParam] -> Either String [(Text, EncodedParam)] Source #
Parameters encoded, checked and named: the positional ones @pN by their position among the positional ones.
positionalName :: Int -> Text Source #
@p and the number.
reservedNameProblem :: Text -> Maybe String Source #
A named parameter can't be called @pN: that is how the positional
parameters are named.
paramNameProblem :: Text -> Maybe String Source #
Why a parameter name can't be used, if it can't: it must be a T-SQL
variable name, @ followed by one or more letters, combining marks,
decimal digits, @, #, $ or _ (Unicode ones included, but only
from the Basic Multilingual Plane: SQL Server rejects surrogates in
identifiers). The query functions' parameter names are spliced into the
sp_executesql declaration, where anything else (a space, a comma, a
parenthesis, a comment) would change what is declared. callProcedure
doesn't use this check: its parameter names are sent as data, and the
server reports the ones it can't match. SQL Server itself accepts a few
more names (a bare @, and ignores format characters such as U+200D
and trailing spaces in RPC parameter names), and rejects some letters
added in recent Unicode versions; it enforces its 128-character limit
itself.
readStep :: ResponseReader -> RowRead r -> IO (ResponseStep r) Source #
The next thing in the response (nextStep), with the rows decoded
by the given function: a batch of rows, a token other than a row or
a nonfatal ERROR (withheld), or StepEnd, which throws the withheld error (or
SevereError) instead if there was one. A response that ends with
the connection closed after an error (by the server, as after a
severity 20 error, or by a failed transport) throws that error; after
close, the ConnectionClosed that every use of the
connection gets. (The withheld error is the reader's, not a stream's:
a stream run again from a step before the error would otherwise report
an error it hadn't seen.)
A fatal ERROR is thrown by the common token reader immediately and leaves the connection broken.
Reading one statement of a batch query (respBatch): the statement's
DONEPROC is returned and then StepEnd, for as long as the statement
stays the current one; an ERROR token isn't withheld but ends the batch
(scopeFail), and the response's end throws SevereError for a
failed DONE but never a withheld error, which there is none of.
readStepReversed :: ResponseReader -> RowRead r -> IO (ResponseStep r) Source #
readStepUsing :: Bool -> ResponseReader -> RowRead r -> IO (ResponseStep r) Source #
ignoreRows :: RowRead () Source #
Skip the rows without decoding them. A row before the first COLMETADATA
is a ProtocolError, since there are no columns to skip it by, so the
result-set loops need no state for that case.
drainResponse :: ResponseReader -> IO () Source #
Read the rest of the response and discard it. The withheld error, if any, is thrown at the end. Nothing to do once the end has been read.
yieldRows :: ResponseReader -> [r] -> Stream (Of r) IO () -> Stream (Of r) IO () Source #
Yield the rows of a batch, then continue. Before each row, the
response must still be the current one (checkCurrent): the rows of
a batch are read from the connection together, but a stream whose
response was superseded by a later request (or canceled, or drained)
throws ResultAbandoned at the next row it is asked for, not after
the rows it already had.
type RowCompiler r = TdsContext -> [ColumnInfo] -> Either DecodeError (CompiledRow r) Source #
How to turn a result set's columns into a per-row decoding function.
compilerFor :: RowDecoder r -> RowCompiler r Source #
compilerForM :: RowDecoderMonadic r -> RowCompiler r Source #
A RowDecoderMonadic runs per row (later fields may depend on earlier
values). The completed decoder must consume every column; prefixes may
be composed inside it. An empty result set cannot be checked this way.
sqlRowCompiler :: RowCompiler SqlRow Source #
How queryMulti and callProcedure decode: every column as a
SqlValue, with the decoders compiled once per result set.
firstResultSet :: RowCompiler r -> ResponseReader -> IO (Maybe (RowRead r)) Source #
Skip to the first result set: its decoder, compiled, or Nothing if
the response has none. On a compile failure the rest of the response
is drained before the error is thrown.
endsResultSet :: Token -> Bool Source #
Whether a token ends the result set whose rows are being read.
foldFirstResultSet :: RowCompiler r -> ResponseReader -> a -> (a -> r -> IO a) -> IO a Source #
Fold over the rows of the first result set, a batch at a time, then
drain the rest of the response. A row that doesn't decode drains the
rest of the response before its DecodeError is thrown. Before each
call of the step, the response must still be the current one
(checkCurrent, as a queryS stream checks before each row): a step
that abandons it (by making another request on the connection, or
closing it) is the last to run, and the fold throws ResultAbandoned
rather than run the steps for the rest of the batch it had.
foldBatches :: RowCompiler r -> ResponseReader -> a -> (a -> [r] -> IO a) -> IO a Source #
foldFirstResultSet a batch (the rows of one packet) at a time.
foldBatchesUsing :: (ResponseReader -> RowRead r -> IO (ResponseStep r)) -> RowCompiler r -> ResponseReader -> a -> (a -> [r] -> IO a) -> IO a Source #
readFirstResultSet :: RowCompiler r -> ResponseReader -> IO [r] Source #
The rows of the first result set, decoded, and the rest of the response drained.
newtype ReversedBatch r Source #
Constructors
| ReversedBatch [r] |
joinReversedBatches :: [ReversedBatch r] -> [r] Source #
streamFirstResultSet :: RowCompiler r -> ResponseReader -> IO () -> Stream (Of r) IO () Source #
Rows of the first result set, decoded, a batch (the rows of one
packet) per effect; then the given action, which reads the rest of the
response (drainResponse for a query of its own).
type StatementEncoder s a = TdsContext -> s -> a -> Either String (Text, RpcRequest, s) Source #
How to encode each item of a list as a statement: its text and its RPC, or why it can't be sent. The state is what one item passes on to the next.
queryStatement :: StatementEncoder () Query Source #
A Query as its sp_executesql call.
statementsRequest :: [(Text, RpcRequest)] -> IO Request Source #
One message of statements. It is named by its last statement's text
(busyStatements): the statement a batchQueryS
stream reads, which is what a message left unfinished is.
statementMessageBytes :: Int Source #
About how many bytes of statements runStatements sends per message.
takeStatements :: StatementEncoder s a -> TdsContext -> s -> Int -> [a] -> Either String ([(Text, RpcRequest)], Int, [a], s) Source #
The statements of the next message, encoded (with the text of each),
how many there are, the items after them and the encoder's state; or
why one can't be sent. i is the position of the first in the
caller's list.
joinBatches :: [[r]] -> [r] Source #
The batches, newest first, as one list in order: one list cell per row, and none for the last batch, which is the list's tail as it is.
exactlyOne :: [r] -> IO r Source #
readResultSets :: RowCompiler r -> ResponseReader -> IO [ResultSet r] Source #
Every result set the reader has left, each decoded by the compiler.
readResultSetsWith :: ResultSets a -> ResponseReader -> IO a Source #
Run the decoder over what the reader has left, then drain the rest.