Module Database.KeyDatabaseSQLite

This module provides a general interface for databases (persistent predicates) where each entry consists of a key and an info part. The key is an integer and the info is arbitrary. All functions are parameterized with a dynamic predicate that takes an integer key as a first parameter.

This module is based on the SQLite database engine. In order to use it you need to have sqlite3 in your PATH environment variable or adjust the value of the constant path[to](#to)sqlite3.

Author: Sebastian Fischer with changes by Michael Hanus

Version: June 2021

Summary of exported operations:

runQ :: Query a -> IO a  Deterministic 
Runs a database query in the IO monad.
transformQ :: (a -> b) -> Query a -> Query b  Deterministic 
Applies a function to the result of a database query.
runT :: Transaction a -> IO (Either a TError)  Deterministic 
Runs a transaction atomically in the IO monad.
runJustT :: Transaction a -> IO a  Deterministic 
Executes a possibly composed transaction on the current state of dynamic predicates as a single transaction.
getDB :: Query a -> Transaction a  Deterministic 
Lifts a database query to the transaction type such that it can be composed with other transactions.
returnT :: a -> Transaction a  Deterministic 
Returns the given value in a transaction that does not access the database.
doneT :: Transaction ()  Deterministic 
Returns the unit value in a transaction that does not access the database.
errorT :: TError -> Transaction a  Deterministic 
Aborts a transaction with an error.
failT :: String -> Transaction a  Deterministic 
Aborts a transaction with a user-defined error message.
(|>>=) :: Transaction a -> (a -> Transaction b) -> Transaction b  Deterministic 
Combines two transactions into a single transaction that executes both in sequence.
(|>>) :: Transaction a -> Transaction b -> Transaction b  Deterministic 
Combines two transactions to execute them in sequence.
sequenceT :: [Transaction a] -> Transaction [a]  Deterministic 
Executes a list of transactions sequentially and computes a list of all results.
sequenceT_ :: [Transaction a] -> Transaction ()  Deterministic 
Executes a list of transactions sequentially, ignoring their results.
mapT :: (a -> Transaction b) -> [a] -> Transaction [b]  Deterministic 
Applies a function that yields transactions to all elements of a list, executes the transaction sequentially, and collects their results.
mapT_ :: (a -> Transaction b) -> [a] -> Transaction ()  Deterministic 
Applies a function that yields transactions to all elements of a list, executes the transactions sequentially, and ignores their results.
persistentSQLite :: String -> String -> [String] -> Int -> a -> Dynamic  Deterministic 
This function is used instead of codedynamic/code or codepersistent/code to declare predicates whose facts are stored in an SQLite database.
existsDBKey :: (Int -> a -> Dynamic) -> Int -> Query Bool  Non-deterministic 
Checks whether the predicate has an entry with the given key.
allDBKeys :: (Int -> a -> Dynamic) -> Query [Int]  Non-deterministic 
Returns a list of all stored keys.
allDBInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> Query [a]  Non-deterministic 
Returns a list of all info parts of stored entries.
allDBKeyInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> Query [(Int,a)]  Non-deterministic 
Returns a list of all stored entries.
(@=) :: Show a => Int -> a -> ColVal  Deterministic 
Constructs a value restriction for the column given as first argument
someDBKeys :: (Int -> a -> Dynamic) -> [ColVal] -> Query [Int]  Non-deterministic 
Returns a list of those stored keys where the corresponding info part matches the gioven value restriction.
someDBInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> [ColVal] -> Query [a]  Non-deterministic 
Returns a list of those info parts of stored entries that match the given value restrictions for columns.
someDBKeyInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> [ColVal] -> Query [(Int,a)]  Non-deterministic 
Returns a list of those entries that match the given value restrictions for columns.
someDBKeyProjections :: (Read a, Show a) => (Int -> b -> Dynamic) -> [Int] -> [ColVal] -> Query [(Int,a)]  Non-deterministic 
Returns a list of column projections on those entries that match the given value restrictions for columns.
getDBInfo :: (Read a, Show a) => (Int -> a -> Dynamic) -> Int -> Query (Maybe a)  Non-deterministic 
Queries the information stored under the given key.
getDBInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> [Int] -> Query (Maybe [a])  Non-deterministic 
Queries the information stored under the given keys.
deleteDBEntry :: (Int -> a -> Dynamic) -> Int -> Transaction ()  Deterministic 
Deletes the information stored under the given key.
deleteDBEntries :: (Int -> a -> Dynamic) -> [Int] -> Transaction ()  Deterministic 
Deletes the information stored under the given keys.
updateDBEntry :: Show a => (Int -> a -> Dynamic) -> Int -> a -> Transaction ()  Non-deterministic 
Updates the information stored under the given key.
newDBEntry :: Show a => (Int -> a -> Dynamic) -> a -> Transaction Int  Non-deterministic 
Stores new information in the database and yields the newly generated key.
newDBKeyEntry :: Show a => (Int -> a -> Dynamic) -> Int -> a -> Transaction ()  Non-deterministic 
Stores a new entry in the database under a given key.
cleanDB :: (Int -> a -> Dynamic) -> Transaction ()  Deterministic 
Deletes all entries from the database associated with a predicate.
closeDBHandles :: IO ()  Deterministic 
Closes all database connections.
showTError :: TError -> String  Deterministic 
Transforms a transaction error into a string.

Exported datatypes:


Query

Queries can read but not write to the database.

Constructors:


Transaction

Transactions can modify the database and are executed atomically.

Constructors:


Dynamic

Result type of database predicates.

Constructors:


Key

The general type of database keys.

Type synonym: Key = Int


KeyPred

Type synonym: KeyPred a = Key -> a -> Dynamic


ColVal

Abstract type for value restrictions

Constructors:


TError

The type of errors that might occur during a transaction.

Constructors:


TErrorKind

The various kinds of transaction errors.

Constructors:

  • KeyNotExistsError :: TErrorKind
  • NoRelationshipError :: TErrorKind
  • DuplicateKeyError :: TErrorKind
  • KeyRequiredError :: TErrorKind
  • UniqueError :: TErrorKind
  • MinError :: TErrorKind
  • MaxError :: TErrorKind
  • UserDefinedError :: TErrorKind
  • ExecutionError :: TErrorKind

Exported operations:

runQ :: Query a -> IO a  Deterministic 

Runs a database query in the IO monad.

Further infos:
  • solution complete, i.e., able to compute all solutions

transformQ :: (a -> b) -> Query a -> Query b  Deterministic 

Applies a function to the result of a database query.

runT :: Transaction a -> IO (Either a TError)  Deterministic 

Runs a transaction atomically in the IO monad.

Transactions are emimmediate/em, which means that locks are acquired on all databases as soon as the transaction is started. After one transaction is started, no other database connection will be able to write to the database or start a transaction. Other connections emcan/em read the database during a transaction of another process.

The choice to use immediate rather than deferred transactions is conservative. It might also be possible to allow multiple simultaneous transactions that lock tables on the first database access (which is the default in SQLite). However this leads to unpredictable order in which locks are taken when multiple databases are involved. The current implementation fixes the locking order by sorting databases by their name and locking them in order immediately when a transaction begins.

More information on a href="http://sqlite.org/lang_transaction.html"transactions/a in SQLite is available online.

runJustT :: Transaction a -> IO a  Deterministic 

Executes a possibly composed transaction on the current state of dynamic predicates as a single transaction. Similar to coderunT/code but a run-time error is raised if the execution of the transaction fails.

getDB :: Query a -> Transaction a  Deterministic 

Lifts a database query to the transaction type such that it can be composed with other transactions. Run-time errors that occur during the execution of the given query are transformed into transaction errors.

returnT :: a -> Transaction a  Deterministic 

Returns the given value in a transaction that does not access the database.

doneT :: Transaction ()  Deterministic 

Returns the unit value in a transaction that does not access the database. Useful to ignore results when composing transactions.

errorT :: TError -> Transaction a  Deterministic 

Aborts a transaction with an error.

failT :: String -> Transaction a  Deterministic 

Aborts a transaction with a user-defined error message.

(|>>=) :: Transaction a -> (a -> Transaction b) -> Transaction b  Deterministic 

Combines two transactions into a single transaction that executes both in sequence. The first transaction is executed, its result passed to the function which computes the second transaction, which is then executed to compute the final result.

If the first transaction is aborted with an error, the second transaction is not executed.

Further infos:
  • defined as left-associative infix operator with precedence 1

(|>>) :: Transaction a -> Transaction b -> Transaction b  Deterministic 

Combines two transactions to execute them in sequence. The result of the first transaction is ignored.

Further infos:
  • defined as left-associative infix operator with precedence 1

sequenceT :: [Transaction a] -> Transaction [a]  Deterministic 

Executes a list of transactions sequentially and computes a list of all results.

sequenceT_ :: [Transaction a] -> Transaction ()  Deterministic 

Executes a list of transactions sequentially, ignoring their results.

mapT :: (a -> Transaction b) -> [a] -> Transaction [b]  Deterministic 

Applies a function that yields transactions to all elements of a list, executes the transaction sequentially, and collects their results.

mapT_ :: (a -> Transaction b) -> [a] -> Transaction ()  Deterministic 

Applies a function that yields transactions to all elements of a list, executes the transactions sequentially, and ignores their results.

persistentSQLite :: String -> String -> [String] -> Int -> a -> Dynamic  Deterministic 

This function is used instead of codedynamic/code or codepersistent/code to declare predicates whose facts are stored in an SQLite database.

If the provided database or the table do not exist they are created automatically when the declared predicate is accessed for the first time.

Multiple column names can be provided if the second argument of the predicate is a tuple with a matching arity. Other record types are not supported. If no column names are provided a table with a single column called codeinfo/code is created. Columns of name coderowid/code are not supported and lead to a run-time error.

Example call:
(persistentSQLite dbFile tableName colNames)
Parameters:
  • dbFile : the name of the associated database file
  • tableName : the name of the associated database table
  • colNames : the column names of the associated database table

existsDBKey :: (Int -> a -> Dynamic) -> Int -> Query Bool  Non-deterministic 

Checks whether the predicate has an entry with the given key.

allDBKeys :: (Int -> a -> Dynamic) -> Query [Int]  Non-deterministic 

Returns a list of all stored keys. Do not use this function unless the database is small.

allDBInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> Query [a]  Non-deterministic 

Returns a list of all info parts of stored entries. Do not use this function unless the database is small.

allDBKeyInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> Query [(Int,a)]  Non-deterministic 

Returns a list of all stored entries. Do not use this function unless the database is small.

(@=) :: Show a => Int -> a -> ColVal  Deterministic 

Constructs a value restriction for the column given as first argument

someDBKeys :: (Int -> a -> Dynamic) -> [ColVal] -> Query [Int]  Non-deterministic 

Returns a list of those stored keys where the corresponding info part matches the gioven value restriction. Safe to use even on large databases if the number of results is small.

someDBInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> [ColVal] -> Query [a]  Non-deterministic 

Returns a list of those info parts of stored entries that match the given value restrictions for columns. Safe to use even on large databases if the number of results is small.

someDBKeyInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> [ColVal] -> Query [(Int,a)]  Non-deterministic 

Returns a list of those entries that match the given value restrictions for columns. Safe to use even on large databases if the number of results is small.

someDBKeyProjections :: (Read a, Show a) => (Int -> b -> Dynamic) -> [Int] -> [ColVal] -> Query [(Int,a)]  Non-deterministic 

Returns a list of column projections on those entries that match the given value restrictions for columns. Safe to use even on large databases if the number of results is small.

getDBInfo :: (Read a, Show a) => (Int -> a -> Dynamic) -> Int -> Query (Maybe a)  Non-deterministic 

Queries the information stored under the given key. Yields codeNothing/code if the given key is not present.

getDBInfos :: (Read a, Show a) => (Int -> a -> Dynamic) -> [Int] -> Query (Maybe [a])  Non-deterministic 

Queries the information stored under the given keys. Yields codeNothing/code if a given key is not present.

deleteDBEntry :: (Int -> a -> Dynamic) -> Int -> Transaction ()  Deterministic 

Deletes the information stored under the given key. If the given key does not exist this transaction is silently ignored and no error is raised.

deleteDBEntries :: (Int -> a -> Dynamic) -> [Int] -> Transaction ()  Deterministic 

Deletes the information stored under the given keys. No error is raised if (some of) the keys do not exist.

updateDBEntry :: Show a => (Int -> a -> Dynamic) -> Int -> a -> Transaction ()  Non-deterministic 

Updates the information stored under the given key. The transaction is aborted with a codeKeyNotExistsError/code if the given key is not present in the database.

newDBEntry :: Show a => (Int -> a -> Dynamic) -> a -> Transaction Int  Non-deterministic 

Stores new information in the database and yields the newly generated key.

newDBKeyEntry :: Show a => (Int -> a -> Dynamic) -> Int -> a -> Transaction ()  Non-deterministic 

Stores a new entry in the database under a given key. The transaction fails if the key already exists.

Example call:
(newDBKeyEntry db key info)
Parameters:
  • db : the database (a dynamic predicate)
  • key : the key of the new entry (an integer)
  • info : the information to be stored in the new entry

cleanDB :: (Int -> a -> Dynamic) -> Transaction ()  Deterministic 

Deletes all entries from the database associated with a predicate.

closeDBHandles :: IO ()  Deterministic 

Closes all database connections. Should be called when no more database access will be necessary.

showTError :: TError -> String  Deterministic 

Transforms a transaction error into a string.