This repository has been archived by the owner on Jun 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathArgonaut.purs
132 lines (122 loc) · 3.95 KB
/
Argonaut.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
-- | An example of using `purescript-sql-squared` library
-- | Having an array of `Json`s construct a list of Sql² projections
module Test.Argonaut where
import Test.Prelude
import Data.Argonaut (JCursor(..), jsonParser)
import Data.Argonaut as JS
import Data.Either (fromRight')
import Data.Foldable as F
import Data.HugeInt as HI
import Data.Json.Extended.Signature (EJsonF(..))
import Data.List ((:))
import Data.List as L
import Data.Maybe (Maybe(..))
import Data.Set as Set
import Data.Tuple (Tuple, fst)
import Matryoshka (ana, elgotPara, Coalgebra, ElgotAlgebra)
import Partial.Unsafe (unsafeCrashWith)
import SqlSquared as S
import SqlSquared.Utils ((×), (∘), (⋙))
data UnfoldableJC = JC JCursor | S String | I Int
jcCoalgebra ∷ Coalgebra (S.SqlF EJsonF) UnfoldableJC
jcCoalgebra = case _ of
S s → S.Identifier (S.Ident s)
I i → S.Literal (Integer (HI.fromInt i))
JC cursor → case cursor of
JCursorTop → S.Splice Nothing
JIndex i c → S.Binop { op: S.IndexDeref, lhs: JC c, rhs: I i }
JField f c → S.Binop { op: S.FieldDeref, lhs: JC c, rhs: S f }
jcursorToSql ∷ JCursor → S.Sql
jcursorToSql = JS.insideOut ⋙ JC ⋙ ana jcCoalgebra
fields ∷ Array JS.Json → L.List S.Sql
fields arr =
map jcursorToSql $ L.fromFoldable $ F.foldMap (Set.fromFoldable ∘ map fst) $ map JS.toPrims arr
allParentsF ∷ ElgotAlgebra (Tuple S.Sql) (S.SqlF EJsonF) (L.List S.Sql)
allParentsF (parent × sqlF) = case sqlF of
S.Splice (Just ps) → ps
S.Unop { op: S.FlattenArrayValues, expr } → parent : expr
S.Unop { op: S.FlattenMapValues, expr } → parent : expr
S.Binop { op: S.FieldDeref, lhs } → parent : lhs
S.Binop { op: S.IndexDeref, lhs } → parent : lhs
_ → L.Nil
allParents ∷ S.Sql → L.List S.Sql
allParents = elgotPara allParentsF
allFields ∷ Array JS.Json → L.List S.Sql
allFields =
L.fromFoldable ∘ F.foldMap (Set.fromFoldable ∘ allParents) ∘ fields
jarray ∷ Array JS.Json
jarray =
map (fromRight' (\_ → unsafeCrashWith "jarray parse failed") ∘ jsonParser) jsonStrings
where
jsonStrings =
[ """{"foo": [{"bar": 1}, 12], "bar": {"baz": false}}"""
, """{"foo": true}"""
, """[12, null]"""
]
testSuite ∷ Test
testSuite =
suite "tests for argonaut example" do
test "interpretation works"
let
expected =
"*.foo[1][2][0]"
: "*.foo.bar.baz"
: L.Nil
js =
(JField "foo" $ JIndex 1 $ JIndex 2 $ JIndex 0 $ JCursorTop)
: (JField "foo" $ JField "bar" $ JField "baz" $ JCursorTop)
: L.Nil
in
assertEqual { expected, actual: map (S.print ∘ jcursorToSql) js }
test "extraction of fields works"
let
actualFields =
Set.fromFoldable
$ map S.print $ fields jarray
expectedFields =
Set.fromFoldable
$ "*[0]"
: "*[1]"
: "*.foo"
: "*.foo[1]"
: "*.foo[0].bar"
: "*.bar.baz"
: L.Nil
in
assertEqual { expected: expectedFields, actual: actualFields }
test "allParents extracted"
let
field =
jcursorToSql
$ JField "foo"
$ JField "bar"
$ JIndex 0
$ JField "baz"
$ JIndex 1
$ JCursorTop
expected =
Set.fromFoldable
$ "*.foo"
: "*.foo.bar"
: "*.foo.bar[0]"
: "*.foo.bar[0].baz"
: "*.foo.bar[0].baz[1]"
: L.Nil
in
assertEqual { expected, actual: Set.fromFoldable $ map S.print $ allParents field }
test "allFields works"
let
actualFields = Set.fromFoldable $ map S.print $ allFields jarray
expectedFields =
Set.fromFoldable
$ "*[0]"
: "*[1]"
: "*.foo"
: "*.foo[1]"
: "*.foo[0]"
: "*.foo[0].bar"
: "*.bar.baz"
: "*.bar"
: L.Nil
in
assertEqual { expected: expectedFields, actual: actualFields }