aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Alexander Foremny <aforemny@posteo.de>2024-02-06 14:29:28 +0100
committerLibravatar Alexander Foremny <aforemny@posteo.de>2024-02-06 14:29:28 +0100
commitedc24dd5b991b32be862e4e9410bc9062bcdbfe1 (patch)
treeb7600ff26a8786938bb591509a2e42e1086bace5
parent542fe6edb8ff35907f06b20182bb8692c357f29b (diff)
support qualified fields
-rw-r--r--app/Main.hs75
1 files changed, 55 insertions, 20 deletions
diff --git a/app/Main.hs b/app/Main.hs
index 3747dab..d650a33 100644
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -13,7 +13,7 @@ import Data.Set qualified as S
import Data.String (IsString (fromString))
import Data.Text qualified as T
import Debug.Trace (trace)
-import System.Directory (listDirectory)
+import System.Directory (listDirectory, setCurrentDirectory)
import System.FilePath (takeExtension, (</>))
import Text.Megaparsec qualified as P
import Text.Megaparsec.Char qualified as P
@@ -24,19 +24,33 @@ debug :: Show a => String -> a -> a
debug s x = trace (printf "%s: %s" s (show x)) x
main = do
+ setCurrentDirectory "./data"
-- query "SELECT . FROM c"
- query' $ Select ["."] "./data/c" [] []
+ query' $ Select [Unqualified "."] "c" [] []
putStrLn ""
-- query "SELECT id FROM c"
- query' $ Select ["id"] "./data/c" [] []
+ query' $ Select [Qualified "c" "id"] "c" [] []
putStrLn ""
-- query "SELECT c.id, j.id, is_j FROM c JOIN j WHERE j.id == c.j_id"
- query' $ Select ["c.id", "j.id", "is_j"] "./data/c" ["./data/j"] [Eq "j.id" "c.j_id"]
+ query' $
+ Select
+ [ Qualified "c" "id",
+ Qualified "j" "id",
+ Unqualified "is_j"
+ ]
+ "c"
+ ["j"]
+ [ Eq (Qualified "j" "id") (Qualified "c" "j_id")
+ ]
data Query
= Select [Field] Collection Join Where
+ deriving (Show)
-type Field = T.Text
+data Field
+ = Qualified FilePath T.Text
+ | Unqualified T.Text
+ deriving (Show)
type Collection = FilePath
@@ -46,6 +60,11 @@ type Where = [Cmp]
data Cmp
= Eq Field Field
+ deriving (Show)
+
+data Record a
+ = Record FilePath a
+ deriving (Show, Eq)
{-
instance IsString Query where
@@ -54,8 +73,8 @@ instance IsString Query where
query :: Query -> IO [J.Value]
query (Select fs c js ws) = do
- c' <- mapM (decodeFile . (c </>)) =<< ls c
- js' <- mapM (\j -> mapM (decodeFile . (j </>)) =<< ls j) js
+ c' <- mapM (fmap (Record c) . decodeFile . (c </>)) =<< ls c
+ js' <- mapM (\j -> mapM (fmap (Record j) . decodeFile . (j </>)) =<< ls j) js
pure $ map (select fs) $ where_ ws $ combine c' js'
combine c = combine' (map (: []) c)
@@ -76,18 +95,29 @@ decodeFile :: J.FromJSON a => FilePath -> IO a
decodeFile =
fmap (fromMaybe (throw DecodeException)) . J.decodeFileStrict
-select :: [T.Text] -> [J.Value] -> J.Value
+select :: [Field] -> [Record J.Value] -> J.Value
select fs vs = join' $ map (select' fs) vs
-select' :: [T.Text] -> J.Value -> J.Value
-select' ["."] (J.Object kvs) = J.Object kvs
-select' fs (J.Object kvs) =
- J.Object (JM.filterWithKey (\k _ -> JK.toText k `elem` fs) kvs)
+select' :: [Field] -> Record J.Value -> Record J.Value
+select' [Unqualified "."] v = v
+select' fs (Record c (J.Object kvs)) =
+ Record c . J.Object $
+ JM.fromList . mapMaybe match . JM.toList $
+ kvs
+ where
+ match (k, v) = case filter (matches (Record c (JK.toText k))) fs of
+ (Qualified _ _ : _) -> Just (JK.fromString (c <> "." <> JK.toString k), v)
+ (Unqualified _ : _) -> Just (k, v)
+ _ -> Nothing
+
+matches :: Record T.Text -> Field -> Bool
+matches (Record c k) (Qualified c' k') = c == c' && k == k'
+matches (Record _ k) (Unqualified k') = k == k'
-join' :: [J.Value] -> J.Value
-join' vs = foldl' merge (J.Object JM.empty) vs
+join' :: [Record J.Value] -> J.Value
+join' vs = foldl' merge (J.Object JM.empty) (map (\(Record _ v) -> v) vs)
-where_ :: Where -> [[J.Value]] -> [[J.Value]]
+where_ :: Where -> [[Record J.Value]] -> [[Record J.Value]]
where_ ws vss = filter (\vs -> all (\w -> satisfy w vs) ws) vss
where
satisfy (Eq f f') vs = unique f vs == unique f' vs
@@ -97,13 +127,17 @@ data DuplicateField' = DuplicateField'
instance Exception DuplicateField'
-unique :: T.Text -> [J.Value] -> J.Value
-unique f as = case debug "unique" $ mapMaybe (get (debug "f" f)) (debug "as" as) of
- [x] -> x
+unique :: Field -> [Record J.Value] -> J.Value
+unique f as = case mapMaybe (get f) as of
+ [Record _ v] -> v
(_ : _) -> throw DuplicateField'
-get :: T.Text -> J.Value -> Maybe J.Value
-get f (J.Object kvs) = JM.lookup (JK.fromText f) kvs
+get :: Field -> Record J.Value -> Maybe (Record J.Value)
+get (Unqualified k) (Record c (J.Object kvs)) =
+ Record c <$> JM.lookup (JK.fromText k) kvs
+get (Qualified c' k) (Record c (J.Object kvs))
+ | c' == c = Record c <$> JM.lookup (JK.fromText k) kvs
+ | otherwise = Nothing
data DuplicateField = DuplicateField
deriving (Show)
@@ -116,6 +150,7 @@ merge (J.Object kvs) (J.Object kvs') =
True -> J.Object (JM.union kvs kvs')
False -> throw DuplicateField
+disjoint :: JM.KeyMap v -> JM.KeyMap v -> Bool
disjoint kvs kvs' =
let ks = S.fromList (JM.keys kvs)
ks' = S.fromList (JM.keys kvs')