Copyright | (c) 2015 Călin Ardelean |
---|---|
License | MIT |
Maintainer | Călin Ardelean <calinucs@gmail.com> |
Stability | experimental |
Portability | portable |
Safe Haskell | None |
Language | Haskell2010 |
Extensions |
|
The Transaction
monad and its primitive queries.
All queries in this module are run on indexes and perform an O(log n) worst case operation.
Functions whose name end in ' do the same operation as their counterparts, but return only the keys, without performing any I/O. They can be used to implement various kinds of joins not supported by the primitive operations.
- module Database.Muesli.Types
- module Database.Muesli.Backend.Types
- data Transaction l m a
- runQuery :: (MonadIO m, LogState l) => Handle l -> Transaction l m a -> m (Either TransactionAbort a)
- data TransactionAbort
- lookup :: (Document a, LogState l, MonadIO m) => Reference a -> Transaction l m (Maybe a)
- insert :: (Document a, MonadIO m) => a -> Transaction l m (Reference a)
- update :: forall a l m. (Document a, MonadIO m) => Reference a -> a -> Transaction l m ()
- delete :: MonadIO m => Reference a -> Transaction l m ()
- data SortOrder
- range :: (Document a, ToKey (Sortable b), LogState l, MonadIO m) => Int -> Property a -> Maybe (Sortable b) -> Maybe (Reference a) -> SortOrder -> Transaction l m [(Reference a, a)]
- range' :: (Document a, ToKey (Sortable b), MonadIO m) => Int -> Property a -> Maybe (Sortable b) -> Maybe (Reference a) -> SortOrder -> Transaction l m [Reference a]
- filterRange :: (Document a, ToKey (Sortable b), LogState l, MonadIO m) => Int -> Property a -> Maybe (Reference c) -> Property a -> Maybe (Sortable b) -> Maybe (Reference a) -> SortOrder -> Transaction l m [(Reference a, a)]
- filterRange' :: (Document a, ToKey (Sortable b), LogState l, MonadIO m) => Int -> Property a -> Maybe (Reference c) -> Property a -> Maybe (Sortable b) -> Maybe (Reference a) -> SortOrder -> Transaction l m [Reference a]
- filter :: (Document a, LogState l, MonadIO m) => Property a -> Maybe (Reference b) -> Property a -> SortOrder -> Transaction l m [(Reference a, a)]
- filter' :: (Document a, LogState l, MonadIO m) => Property a -> Maybe (Reference b) -> Property a -> SortOrder -> Transaction l m [Reference a]
- unique :: (Document a, LogState l, ToKey (Unique b), MonadIO m) => Property a -> Unique b -> Transaction l m (Maybe (Reference a, a))
- unique' :: (ToKey (Unique b), MonadIO m) => Property a -> Unique b -> Transaction l m (Maybe (Reference a))
- updateUnique :: (Document a, ToKey (Unique b), MonadIO m) => Property a -> Unique b -> a -> Transaction l m (Reference a)
- size :: (Document a, MonadIO m) => Property a -> Transaction l m Int
Documentation
module Database.Muesli.Types
The Transaction monad
data Transaction l m a Source
Abstract monad for writing and evaluating queries under ACID semantics.
The l
parameter stands for a LogState
backend, m
is a MonadIO
that gets
lifted, so users can run arbitrary IO inside queries, and a
is the result.
Monad m => Monad (Transaction l m) Source | |
Functor m => Functor (Transaction l m) Source | |
Monad m => Applicative (Transaction l m) Source | |
MonadIO m => MonadIO (Transaction l m) Source |
runQuery :: (MonadIO m, LogState l) => Handle l -> Transaction l m a -> m (Either TransactionAbort a) Source
Transaction
evaluation inside a MonadIO
.
Lookups are executed directly, targeting a specific version (TransactionId
)
, while the keys of both read and written documents are collected in the
TransactionState
.
At the end various consistency checks are performed, and the transaction is
aborted in case any fails. See TransactionAbort
for details.
Otherwise, under master lock, space in the data (abstract) file is allocated
with alloc
, and the transaction records are written in the
logPend
, and also in the log file, with logAppend
.
Writing the serialized data to the data file, updating indexes and completing
the transaction is then left for the commitThread
.
Note that transactions are only durable after commitThread
finishes.
In the future we may add a blocking version of runQuery
.
data TransactionAbort Source
Error returned by runQuery
for aborted transactions.
It is an instance of Exception
solely for user convenience,
as the database never throws it.
AbortUnique String | Returned when trying to update an |
AbortConflict String | Returned when there is a conflict with concurrent transactions.
This happenes when the The second part could be relaxed in the future based on a user policy, since overwriting updates are sometimes acceptable. |
AbortDelete String | Returned when trying to delete a document that is still referenced by other documents. TODO: Current implementation is not completely safe in this regard, as updates should also be checked. The reason is that the check is performed on indexes and on the pending log. So there is a small window in which it is possible for a concurrent transaction to update a record deleted by the current one, before adding it to the pending log, without any error. |
Primitive queries
CRUD operations
lookup :: (Document a, LogState l, MonadIO m) => Reference a -> Transaction l m (Maybe a) Source
Dereferences the given key. Returns Nothing
if the key is not found.
insert :: (Document a, MonadIO m) => a -> Transaction l m (Reference a) Source
Inserts a new document and returns its key.
The primary key is generated with mkNewDocumentKey
.
update :: forall a l m. (Document a, MonadIO m) => Reference a -> a -> Transaction l m () Source
Updates a document.
Note that since muesli
is a MVCC database, this means inserting a new
version of the document. The version number is the TransactionId
of the
current transaction. This fact is transparent to the user though.
delete :: MonadIO m => Reference a -> Transaction l m () Source
Deletes a document.
Note that since muesli
is a MVCC database, this means inserting a new
version with the recDeleted
flag set to True
.
But this fact is transparent to the user, since the indexes are updated
as if the record was really deleted.
It will be the job of the gcThread
to actually
clean the transaction log and compact the data file.
Range queries
Sort order for range queries.
:: (Document a, ToKey (Sortable b), LogState l, MonadIO m) | |
=> Int | The |
-> Property a | The |
-> Maybe (Sortable b) | The |
-> Maybe (Reference a) | The |
-> SortOrder | The |
-> Transaction l m [(Reference a, a)] |
Runs a range query on a Sortable
field.
It can be used as a cursor, for precise and efficient paging through a
large dataset. For this purpose you should remember the last Reference
from the previous page and give it as the sortKey argument below.
This is needed since the sortable field may not have unique values, so
remembering just the sortVal is insufficient.
The corresponding SQL is:
SELECT TOP page * FROM table WHERE (sortVal = NULL OR sortFld < sortVal) AND (sortKey = NULL OR ID < sortKey) ORDER BY sortFld, ID sortOrder
range' :: (Document a, ToKey (Sortable b), MonadIO m) => Int -> Property a -> Maybe (Sortable b) -> Maybe (Reference a) -> SortOrder -> Transaction l m [Reference a] Source
Like range
, but returns only the keys.
:: (Document a, ToKey (Sortable b), LogState l, MonadIO m) | |
=> Int | The |
-> Property a | The |
-> Maybe (Reference c) | The |
-> Property a | The |
-> Maybe (Sortable b) | The |
-> Maybe (Reference a) | The |
-> SortOrder | The |
-> Transaction l m [(Reference a, a)] |
Runs a filter-and-range query on a Reference
field, with results sorted
on a different Sortable
field.
Sending Nothing
for filterVal
filters for NULL
values, which correspond
to a Nothing
in a field of type Maybe
(Reference
a). This uses the
special Maybe
instance mentioned at the Indexable
documentation.
The paging behaviour is the same as for range
.
The corresponding SQL is:
SELECT TOP page * FROM table WHERE (filterFld = filterVal) AND (sortVal = NULL OR sortFld < sortVal) AND (sortKey = NULL OR ID < sortKey) ORDER BY sortFld, ID sortOrder
filterRange' :: (Document a, ToKey (Sortable b), LogState l, MonadIO m) => Int -> Property a -> Maybe (Reference c) -> Property a -> Maybe (Sortable b) -> Maybe (Reference a) -> SortOrder -> Transaction l m [Reference a] Source
Like filterRange
, but returns only the keys.
filter :: (Document a, LogState l, MonadIO m) => Property a -> Maybe (Reference b) -> Property a -> SortOrder -> Transaction l m [(Reference a, a)] Source
Runs a filter query on a Reference
field, with results sorted
on a different Sortable
field.
Like filterRange
, but returns all documents, not just a range.
filter' :: (Document a, LogState l, MonadIO m) => Property a -> Maybe (Reference b) -> Property a -> SortOrder -> Transaction l m [Reference a] Source
Like filter
, but returns only the keyes.
Queries on unique fields
unique :: (Document a, LogState l, ToKey (Unique b), MonadIO m) => Property a -> Unique b -> Transaction l m (Maybe (Reference a, a)) Source
unique' :: (ToKey (Unique b), MonadIO m) => Property a -> Unique b -> Transaction l m (Maybe (Reference a)) Source
updateUnique :: (Document a, ToKey (Unique b), MonadIO m) => Property a -> Unique b -> a -> Transaction l m (Reference a) Source