mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-04-30 04:54:59 +08:00
server: support single $ as root json path (#4482)
* support single $ json path * support sql query with root json path * update changelog * update changelog Co-authored-by: Karthikeyan Chinnakonda <karthikeyan@hasura.io> Co-authored-by: Tirumarai Selvan <tiru@hasura.io>
This commit is contained in:
@@ -13,6 +13,7 @@ import Data.Aeson.Internal (JSONPath, JSONPathElement (..))
|
||||
import Data.Attoparsec.Text
|
||||
|
||||
parseJSONPath :: T.Text -> Either String JSONPath
|
||||
parseJSONPath "$" = Right []
|
||||
parseJSONPath txt = first (const invalidMessage) $
|
||||
parseOnly (optional (char '$') *> many1' element <* endOfInput) txt
|
||||
where
|
||||
|
||||
@@ -35,20 +35,23 @@ import Hasura.RQL.Types
|
||||
import Hasura.SQL.Types
|
||||
import Hasura.SQL.Value
|
||||
|
||||
jsonPathToColExp :: (MonadError QErr m) => T.Text -> m S.SQLExp
|
||||
jsonPathToColExp :: (MonadError QErr m) => T.Text -> m (Maybe S.SQLExp)
|
||||
jsonPathToColExp t = case parseJSONPath t of
|
||||
Left s -> throw400 ParseFailed $ T.pack $ "parse json path error: " ++ s
|
||||
Right jPaths -> return $ S.SEArray $ map elToColExp jPaths
|
||||
Right [] -> return Nothing
|
||||
Right jPaths -> return $ Just $ S.SEArray $ map elToColExp jPaths
|
||||
where
|
||||
elToColExp (Key k) = S.SELit k
|
||||
elToColExp (Index i) = S.SELit $ T.pack (show i)
|
||||
|
||||
|
||||
argsToColOp :: (MonadReusability m, MonadError QErr m) => ArgsMap -> m (Maybe RS.ColOp)
|
||||
argsToColOp args = maybe (return Nothing) toOp $ Map.lookup "path" args
|
||||
where
|
||||
toJsonPathExp = fmap (RS.ColOp S.jsonbPathOp) . jsonPathToColExp
|
||||
toOp v = asPGColTextM v >>= traverse toJsonPathExp
|
||||
argsToColOp args = case Map.lookup "path" args of
|
||||
Nothing -> return Nothing
|
||||
Just txt -> do
|
||||
mColTxt <- asPGColTextM txt
|
||||
mColExps <- maybe (return Nothing) jsonPathToColExp mColTxt
|
||||
return $ RS.ColOp S.jsonbPathOp <$> mColExps
|
||||
|
||||
type AnnFlds = RS.AnnFldsG UnresolvedVal
|
||||
|
||||
|
||||
@@ -16,14 +16,20 @@ spec = describe "encode and parse JSONPath" $ do
|
||||
forM_ generateTestEncodeJSONPath $ \(jsonPath, result) ->
|
||||
encodeJSONPath jsonPath `shouldBe` result
|
||||
|
||||
it "JSONPath parser" $
|
||||
withMaxSuccess 1000 $
|
||||
forAll(resize 20 generateJSONPath) $ \jsonPath ->
|
||||
let encPath = encodeJSONPath jsonPath
|
||||
parsedJSONPathE = parseJSONPath $ T.pack encPath
|
||||
in case parsedJSONPathE of
|
||||
Left err -> counterexample (err <> ": " <> encPath) False
|
||||
Right parsedJSONPath -> property $ parsedJSONPath == jsonPath
|
||||
describe "JSONPath parser" $ do
|
||||
|
||||
it "Single $" $
|
||||
parseJSONPath "$" `shouldBe` (Right [] :: Either String JSONPath)
|
||||
|
||||
it "Random json paths" $
|
||||
withMaxSuccess 1000 $
|
||||
forAll (resize 20 generateJSONPath) $ \jsonPath ->
|
||||
let encPath = encodeJSONPath jsonPath
|
||||
parsedJSONPathE = parseJSONPath $ T.pack encPath
|
||||
in case parsedJSONPathE of
|
||||
Left err -> counterexample (err <> ": " <> encPath) False
|
||||
Right parsedJSONPath -> property $ parsedJSONPath == jsonPath
|
||||
|
||||
|
||||
|
||||
generateTestEncodeJSONPath :: [(JSONPath, String)]
|
||||
|
||||
@@ -46,6 +46,17 @@ response:
|
||||
hello world!: hi
|
||||
objs:
|
||||
- 你好: Hello!
|
||||
c32_json_dollar:
|
||||
a: b
|
||||
obj:
|
||||
c1: c2
|
||||
arr: [1,2,3]
|
||||
_underscore: 0
|
||||
'!@#$%^': special
|
||||
translations:
|
||||
hello world!: hi
|
||||
objs:
|
||||
- 你好: Hello!
|
||||
c32_json_child_prop: c2
|
||||
c32_json_child_prop_no_dot: b
|
||||
c32_json_array_item: 1
|
||||
@@ -57,9 +68,20 @@ response:
|
||||
c32_json_nested_special_array_double_quote_dot: Hello!
|
||||
c33_jsonb:
|
||||
c: d
|
||||
arr: [4,5,6]
|
||||
obj:
|
||||
e1: e2
|
||||
arr: [4,5,6]
|
||||
e1: e2
|
||||
objs:
|
||||
- 你好: Hello!
|
||||
'!@#$%^': special
|
||||
_underscore: 0
|
||||
translations:
|
||||
hello world!: hi
|
||||
c33_jsonb_dollar:
|
||||
c: d
|
||||
arr: [4,5,6]
|
||||
obj:
|
||||
e1: e2
|
||||
objs:
|
||||
- 你好: Hello!
|
||||
'!@#$%^': special
|
||||
@@ -130,6 +152,7 @@ query:
|
||||
c30_inet
|
||||
c31_macaddr
|
||||
c32_json
|
||||
c32_json_dollar: c32_json(path: "$")
|
||||
c32_json_child_prop: c32_json(path: ".obj.c1")
|
||||
c32_json_child_prop_no_dot: c32_json(path: "a")
|
||||
c32_json_array_item: c32_json(path: "arr[0]")
|
||||
@@ -140,6 +163,7 @@ query:
|
||||
c32_json_nested_special_array_double_quote: c32_json(path: "objs[0][\"你好\"]")
|
||||
c32_json_nested_special_array_double_quote_dot: c32_json(path: "objs[0].[\"你好\"]")
|
||||
c33_jsonb
|
||||
c33_jsonb_dollar: c33_jsonb(path: "$")
|
||||
c33_jsonb_child_prop: c33_jsonb(path: ".obj.e1")
|
||||
c33_jsonb_child_prop_no_dot: c33_jsonb(path: "c")
|
||||
c33_jsonb_array_item: c33_jsonb(path: "arr[2]")
|
||||
|
||||
Reference in New Issue
Block a user