module Database.HaskRel.Relational.Assignment (
assign,
insert, dInsert, update, updateAll, delete, iDelete, deleteP,
updateA, updateAllA
) where
import Control.Monad ( unless )
import Data.HList.CommonMain
import Data.Set ( Set, filter, difference, fromList, size )
import qualified Data.Set ( map, foldr )
import Data.Typeable ( Typeable )
import System.Directory ( renameFile )
import Database.HaskRel.Relational.Definition ( Relation, RTuple, bodyAsList, relRearrange' )
import Database.HaskRel.HFWTabulation ( HPresentRecAttr, showHRecSetTab )
import Database.HaskRel.Relational.Algebra ( intersect, minus, minus_ )
import Database.HaskRel.Relational.Variable
rewriteRelvar
:: (Show (HList (RecordValuesR r)), RecordValues r) =>
Relvar a -> Relation r -> IO ()
rewriteRelvar rv updated =
do writeRelvarBody ( relvarPath rv ++ ".new" ) ( bodyAsList updated )
renameFile ( relvarPath rv ++ ".new" ) ( relvarPath rv )
assign
:: (Ord (HList a), Show (HList (RecordValuesR a)), RecordValues a,
HRearrange3 (LabelsOf a) r a, HLabelSet (LabelsOf a),
SameLength' r a, SameLength' r (LabelsOf a), SameLength' a r,
SameLength' (LabelsOf a) r) =>
Relvar a -> Relation r -> IO ()
assign rv r = do rewriteRelvar rv ( relRearrange' r $ relvarType rv )
putStrLn $ "Value assigned to " ++ relvarPath rv
appendRelvar :: (Show (t a), Foldable t) => Relvar t1 -> t a -> Bool -> IO ()
appendRelvar rv hll empty =
let prefix = if empty then "" else ","
in unless (null hll)
$ appendFile (relvarPath rv) $ prefix ++ init ( tail $ show hll )
insert
:: (Ord (HList a), Read (HList (RecordValuesR a)),
Show (HList (RecordValuesR a)), RecordValues a,
HRearrange3 (LabelsOf a) r a, HLabelSet (LabelsOf a),
HMapAux HList TaggedFn (RecordValuesR a) a, SameLength' r a,
SameLength' r (LabelsOf a), SameLength' a r,
SameLength' (LabelsOf a) r) =>
Relvar a -> Relation r -> IO ()
insert rv r = do
rv' <- readRelvar rv
let diff = ( r `minus_` rv' )
in do appendRelvar rv ( bodyAsList diff ) ( null rv' )
putStrLn $ "Inserted " ++ show ( size diff ) ++ " of " ++
show ( size r ) ++ " tuples into " ++ relvarPath rv
dInsert
:: (Ord (HList t), Read (HList (RecordValuesR t)),
Show (HList (RecordValuesR r)), Typeable t, RecordValues r,
RecordValues t, HRearrange3 (LabelsOf t) r t,
HLabelSet (LabelsOf t), HMapAux HList TaggedFn (RecordValuesR t) t,
HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR t) [[String]],
SameLength' r t, SameLength' r (LabelsOf t), SameLength' t r,
SameLength' (LabelsOf t) r) =>
Relvar t -> Relation r -> IO ()
dInsert rv r = do
rv' <- readRelvar rv
let inter = ( rv' `intersect` r )
in
if not ( null inter )
then error $ "Unique constraint violation, tuples already present in " ++ relvarPath rv ++ ":\n" ++ showHRecSetTab inter
else
do appendRelvar rv ( bodyAsList r ) ( null rv' )
putStrLn $ "Inserted " ++ show ( size r ) ++ " tuples into " ++ relvarPath rv
funSelfUpdate
:: (HRearrange3 (LabelsOf r') (HAppendListR r r'2) r',
HLabelSet (LabelsOf r'), HLabelSet (LabelsOf (HAppendListR r r'2)),
HDeleteLabels (LabelsOf r) r' r'2, HAppendList r r'2,
SameLength' r' (HAppendListR r r'2),
SameLength' (LabelsOf r') (HAppendListR r r'2),
SameLength' (HAppendListR r r'2) r',
SameLength' (HAppendListR r r'2) (LabelsOf r'),
HAllTaggedLV (HAppendListR r r'2)) =>
(Record r' -> Record r) -> Record r' -> Record r'
funSelfUpdate f t = hRearrange ( labelsOf t ) ( f t .<++. t )
update'
:: (Num t, Num t1, Ord (HList r'),
HRearrange3 (LabelsOf r') (HAppendListR r r'2) r',
HLabelSet (LabelsOf r'), HLabelSet (LabelsOf (HAppendListR r r'2)),
HDeleteLabels (LabelsOf r) r' r'2, HAppendList r r'2,
SameLength' r' (HAppendListR r r'2),
SameLength' (LabelsOf r') (HAppendListR r r'2),
SameLength' (HAppendListR r r'2) r',
SameLength' (HAppendListR r r'2) (LabelsOf r'),
HAllTaggedLV (HAppendListR r r'2)) =>
Set (Record r')
-> (Record r' -> Bool)
-> (Record r' -> Record r)
-> (t, t1, Set (Record r'))
update' r p f = update'' r p (funSelfUpdate f)
updateA'
:: (Num t, Num t1, Ord (record r), HUpdateAtLabel record l v r r,
SameLength' r r) =>
Set (record r) -> (record r -> Bool) -> (record r -> Tagged l v)
-> (t, t1, Set (record r))
updateA' r p f = update'' r p (\t -> f t .<. t)
update'' :: (Num t, Num t1, Ord a) =>
Set a -> (a -> Bool) -> (a -> a) -> (t, t1, Set a)
update'' r p f =
let (a,b,c) = Data.Set.foldr
(\t (a',b',c') ->
if p t then ( a' + 1, b' + 1, f t : c' )
else ( a', b' + 1, t : c' ) )
(0,0,[])
r
in (a, b, fromList c)
updateAll'
:: (Num t, Ord (HList r'),
HRearrange3 (LabelsOf r') (HAppendListR r r'2) r',
HLabelSet (LabelsOf r'), HLabelSet (LabelsOf (HAppendListR r r'2)),
HDeleteLabels (LabelsOf r) r' r'2, HAppendList r r'2,
SameLength' r' (HAppendListR r r'2),
SameLength' (LabelsOf r') (HAppendListR r r'2),
SameLength' (HAppendListR r r'2) r',
SameLength' (HAppendListR r r'2) (LabelsOf r'),
HAllTaggedLV (HAppendListR r r'2)) =>
Set (Record r') -> (Record r' -> Record r) -> (t, Set (Record r'))
updateAll' r f = updateAll'' r (funSelfUpdate f)
updateAllA'
:: (Num t, Ord (record r), HUpdateAtLabel record l v r r,
SameLength' r r) =>
Set (record r) -> (record r -> Tagged l v) -> (t, Set (record r))
updateAllA' r f = updateAll'' r (\t -> f t .<. t)
updateAll'' :: (Num t, Ord a1) => Set a -> (a -> a1) -> (t, Set a1)
updateAll'' r f =
let (a,b) = Data.Set.foldr (\t (a',b') -> ( a' + 1, f t : b' ) ) (0,[]) r
in (a, fromList b)
doUpdate
:: (Show a, Show a1, Show (HList (RecordValuesR r)),
RecordValues r) =>
Relvar a2 -> (a, a1, Relation r) -> IO ()
doUpdate rv ( updCount, totCount, updated ) =
do rewriteRelvar rv updated
putStrLn $ "Updated " ++ show updCount ++ " of " ++ show totCount ++ " tuples in " ++ relvarPath rv
update
:: (Ord (HList a), Read (HList (RecordValuesR a)),
Show (HList (RecordValuesR a)), RecordValues a,
HRearrange3 (LabelsOf a) (HAppendListR r r'2) a,
HLabelSet (LabelsOf a), HLabelSet (LabelsOf (HAppendListR r r'2)),
HDeleteLabels (LabelsOf r) a r'2,
HMapAux HList TaggedFn (RecordValuesR a) a, HAppendList r r'2,
SameLength' a (HAppendListR r r'2),
SameLength' (LabelsOf a) (HAppendListR r r'2),
SameLength' (HAppendListR r r'2) a,
SameLength' (HAppendListR r r'2) (LabelsOf a),
HAllTaggedLV (HAppendListR r r'2)) =>
Relvar a -> (Record a -> Bool) -> (Record a -> Record r) -> IO ()
update rv p f = do
rv' <- readRelvar rv
doUpdate rv ( update' rv' p f )
updateA rv p f = do
rv' <- readRelvar rv
doUpdate rv ( updateA' rv' p f )
doUpdateAll
:: (Show a, Show (HList (RecordValuesR r)), RecordValues r) =>
Relvar a1 -> (a, Relation r) -> IO ()
doUpdateAll rv ( count, updated ) =
do rewriteRelvar rv updated
putStrLn $ "Updated " ++ show count ++ " tuples in " ++ relvarPath rv
updateAll
:: (Ord (HList a), Read (HList (RecordValuesR a)),
Show (HList (RecordValuesR a)), RecordValues a,
HRearrange3 (LabelsOf a) (HAppendListR r r'2) a,
HLabelSet (LabelsOf a), HLabelSet (LabelsOf (HAppendListR r r'2)),
HDeleteLabels (LabelsOf r) a r'2,
HMapAux HList TaggedFn (RecordValuesR a) a, HAppendList r r'2,
SameLength' a (HAppendListR r r'2),
SameLength' (LabelsOf a) (HAppendListR r r'2),
SameLength' (HAppendListR r r'2) a,
SameLength' (HAppendListR r r'2) (LabelsOf a),
HAllTaggedLV (HAppendListR r r'2)) =>
Relvar a -> (Record a -> Record r) -> IO ()
updateAll rv f = do
rv' <- readRelvar rv
doUpdateAll rv (updateAll' rv' f)
updateAllA rv f = do
rv' <- readRelvar rv
doUpdateAll rv (updateAllA' rv' f)
doDelete rv filtered nDeleted =
do writeRelvarBody ( relvarPath rv ++ ".new" ) ( bodyAsList filtered )
renameFile ( relvarPath rv ++ ".new" ) ( relvarPath rv )
putStrLn $ "Deleted " ++ nDeleted ++ " tuples from " ++ relvarPath rv
delete
:: (Ord (HList t), Read (HList (RecordValuesR t)),
Show (HList (RecordValuesR t)), RecordValues t,
HMapAux HList TaggedFn (RecordValuesR t) t) =>
Relvar t -> Relation t -> IO ()
delete rv r = do
rv' <- readRelvar rv
let filtered = Data.Set.difference rv' r
in doDelete rv filtered ( show $ size rv' size filtered )
iDelete
:: (Ord (HList a), Ord (HList t), Read (HList (RecordValuesR t)),
Show (HList (RecordValuesR t)), Typeable a, RecordValues a,
RecordValues t, HRearrange3 (LabelsOf t) a t,
HRearrange3 (LabelsOf a) t a, HLabelSet (LabelsOf t),
HLabelSet (LabelsOf a), HMapAux HList TaggedFn (RecordValuesR t) t,
HFoldr (Mapcar HPresentRecAttr) [[String]] (RecordValuesR a) [[String]],
SameLength' a t, SameLength' a (LabelsOf t), SameLength' t a,
SameLength' t (LabelsOf a), SameLength' (LabelsOf t) a,
SameLength' (LabelsOf a) t) =>
Relvar t -> Relation a -> IO ()
iDelete rv r = do
rv' <- readRelvar rv
let filtered = rv' `minus` r
in if size filtered > ( size rv' size r )
then error $ "Tuples not found in relvar " ++ relvarPath rv ++ ":\n" ++ showHRecSetTab ( r `minus` rv' )
else doDelete rv filtered ( show $ size rv' size filtered )
deleteP
:: (Ord (HList t), Read (HList (RecordValuesR t)),
Show (HList (RecordValuesR t)), RecordValues t,
HMapAux HList TaggedFn (RecordValuesR t) t) =>
Relvar t -> (RTuple t -> Bool) -> IO ()
deleteP rv p = do
rv' <- readRelvar rv
let filtered = Data.Set.filter ( not . p ) rv'
in doDelete rv filtered ( show $ size rv' size filtered )