diff options
Diffstat (limited to 'src/Store/Query')
-rw-r--r-- | src/Store/Query/Field.hs | 10 | ||||
-rw-r--r-- | src/Store/Query/Parser.hs | 67 | ||||
-rw-r--r-- | src/Store/Query/Printer.hs | 5 | ||||
-rw-r--r-- | src/Store/Query/Record.hs | 20 | ||||
-rw-r--r-- | src/Store/Query/Type.hs | 6 |
5 files changed, 58 insertions, 50 deletions
diff --git a/src/Store/Query/Field.hs b/src/Store/Query/Field.hs index 69a0983..3078a34 100644 --- a/src/Store/Query/Field.hs +++ b/src/Store/Query/Field.hs @@ -9,23 +9,19 @@ import Data.Aeson qualified as J import Data.Aeson.Key qualified as JK import Data.Aeson.KeyMap qualified as JM import Data.List (intercalate) -import Data.List.NonEmpty qualified as N import Data.Text qualified as T data Field - = Qualified Collection (N.NonEmpty T.Text) - | Unqualified (N.NonEmpty T.Text) + = Field Collection [T.Text] deriving (Show) toString :: Field -> String -toString (Qualified c ks) = intercalate "." (c : map T.unpack (N.toList ks)) -toString (Unqualified ks) = intercalate "." (map T.unpack (N.toList ks)) +toString (Field c ks) = intercalate "." (c : map T.unpack ks) type Collection = FilePath prefix :: Field -> J.Value -> J.Value -prefix (Qualified c ks) = prefix' (T.pack c : N.toList ks) -prefix (Unqualified ks) = prefix' (N.toList ks) +prefix (Field c ks) = prefix' (T.pack c : ks) prefix' :: [T.Text] -> J.Value -> J.Value prefix' ks v = diff --git a/src/Store/Query/Parser.hs b/src/Store/Query/Parser.hs index 93e408c..cb02f32 100644 --- a/src/Store/Query/Parser.hs +++ b/src/Store/Query/Parser.hs @@ -4,9 +4,8 @@ module Store.Query.Parser () where import Control.Exception (throw) import Control.Monad (void) -import Control.Monad.Combinators.NonEmpty qualified as PN import Data.Char (isSpace) -import Data.List.NonEmpty qualified as N +import Data.Map qualified as M import Data.String (IsString (fromString)) import Data.Text qualified as T import Data.Void (Void) @@ -39,6 +38,7 @@ instance IsString Query where lexeme = P.lexeme $ void $ P.takeWhileP Nothing isSpace and = void $ lexeme (P.string "AND") + colon = void $ lexeme (P.string ":") comma = void $ lexeme (P.string ",") embed = void $ lexeme (P.string "EMBED") eq = void $ lexeme (P.string "==") @@ -84,26 +84,55 @@ instance IsString Query where pure $ Eq a b fieldSelector = - P.choice - [ do - void $ lexeme $ P.string "*" - pure All, - do - Only <$> PN.sepBy1 field comma - ] + lexeme $ + P.choice + [ do + void $ lexeme $ P.string "{" + kvs <- + P.sepBy + ( P.choice + [ P.try do + k <- + lexeme $ + P.takeWhile1P + Nothing + ( \c -> + not (isSpace c) + && c /= '.' + && c /= ',' + && c /= ':' + ) + lexeme $ colon + v <- fieldSelector + pure (k, v), + do + f@(Field c ks) <- field + let k + | null ks = c + | otherwise = T.unpack (last ks) + pure (k, SelectField f) + ] + ) + comma + void $ lexeme $ P.string "}" + pure $ SelectObject (M.fromList kvs), + do + SelectField <$> field + ] field :: P.Parsec Void String Field field = - lexeme . P.choice $ - [ P.try - do - Qualified - <$> (fieldPart <* P.string ".") - <*> (N.map T.pack <$> PN.sepBy1 fieldPart (P.string ".")), - do - Unqualified - <$> (N.map T.pack <$> PN.sepBy1 fieldPart (P.string ".")) - ] + lexeme do + Field + <$> fieldPart + <*> ( P.choice + [ do + void $ P.string "." + map T.pack <$> P.sepBy fieldPart (P.string "."), + do + pure [] + ] + ) fieldPart :: P.Parsec Void String String fieldPart = P.takeWhile1P Nothing (\c -> not (isSpace c) && c /= ',' && c /= '.') diff --git a/src/Store/Query/Printer.hs b/src/Store/Query/Printer.hs index 5692ba8..7861bc9 100644 --- a/src/Store/Query/Printer.hs +++ b/src/Store/Query/Printer.hs @@ -3,7 +3,6 @@ module Store.Query.Printer () where import Data.List (intercalate) -import Data.List.NonEmpty qualified as N import Data.Maybe (catMaybes, mapMaybe) import Store.Query.Field import Store.Query.Type @@ -21,9 +20,7 @@ instance Show Query where showWhereClause w ] where - showFieldSelector All = "*" - showFieldSelector (Only (N.toList -> fs)) = - intercalate ", " (map showField fs) + showFieldSelector = error "showFieldSelector" showField = Store.Query.Field.toString showCollection c = c showJoinClauses js = case map showJoinClause js of diff --git a/src/Store/Query/Record.hs b/src/Store/Query/Record.hs index 71461d5..b00be27 100644 --- a/src/Store/Query/Record.hs +++ b/src/Store/Query/Record.hs @@ -5,7 +5,6 @@ module Store.Query.Record lookup, Records, lookups, - select, disjointUnion, disjointUnions, ) @@ -16,8 +15,7 @@ import Data.Aeson qualified as J import Data.Aeson.Key qualified as JK import Data.Aeson.KeyMap qualified as JM import Data.List (foldl') -import Data.List.NonEmpty qualified as N -import Data.Maybe (fromMaybe, mapMaybe) +import Data.Maybe (mapMaybe) import Data.Text qualified as T import Store.Exception (DuplicateField (DuplicateField)) import Store.Query.Field @@ -36,10 +34,8 @@ toValue :: Record a -> a toValue (Record _ v) = v lookup :: Field -> Record J.Value -> Maybe J.Value -lookup (Unqualified ks) (Record _ v) = - lookup' (N.toList ks) v -lookup (Qualified c' ks) (Record c v) - | c' == c = lookup' (N.toList ks) v +lookup (Field c' ks) (Record c v) + | c' == c = lookup' ks v | otherwise = Nothing lookup' :: [T.Text] -> J.Value -> Maybe J.Value @@ -56,16 +52,6 @@ lookups f rs = [v] -> Just v (_ : _) -> throw (DuplicateField (toString f)) -select :: [Field] -> Records J.Value -> J.Value -select fs rs = - foldl' - union - (J.Object JM.empty) - (map (\f -> prefix f ((fromMaybe J.Null (lookups f rs)))) fs) - -union :: J.Value -> J.Value -> J.Value -union (J.Object r) (J.Object s) = J.Object (JM.unionWith union r s) - disjointUnion :: J.Value -> J.Value -> J.Value disjointUnion (J.Object r) (J.Object s) = J.Object (JM.unionWithKey disjointUnion' r s) diff --git a/src/Store/Query/Type.hs b/src/Store/Query/Type.hs index 5aa0e36..abf2c77 100644 --- a/src/Store/Query/Type.hs +++ b/src/Store/Query/Type.hs @@ -14,7 +14,7 @@ module Store.Query.Type ) where -import Data.List.NonEmpty qualified as N +import Data.Map qualified as M import Store.Query.Field import Store.Query.Record @@ -27,8 +27,8 @@ data Query (Maybe WhereClause) data FieldSelector - = All - | Only (N.NonEmpty Field) + = SelectObject (M.Map String FieldSelector) + | SelectField Field deriving (Show) type Collection = FilePath |