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
/
Argonaut.purs
137 lines (123 loc) · 3.88 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
133
134
135
136
137
-- | An example of using `purescript-sqlsquare` library
-- | Having an array of `Json`s construct a list of Sql² projections
module Test.Argonaut where
import Prelude
import Data.Argonaut (JCursor(..), jsonParser)
import Data.Argonaut as JS
import Data.Either (fromRight)
import Data.Foldable as F
import Data.List ((:))
import Data.List as L
import Data.Maybe (Maybe(..))
import Data.Set as Set
import Data.Tuple (Tuple, fst)
import Data.Json.Extended.Signature (EJsonF(..))
import SqlSquared as S
import SqlSquared.Utils ((×), (∘), (⋙))
import Matryoshka (ana, elgotPara, Coalgebra, ElgotAlgebra)
import Test.Unit (suite, test, TestSuite)
import Test.Unit.Assert as Assert
import Partial.Unsafe (unsafePartial)
data UnfoldableJC = JC JCursor | S String | I Int
jcCoalgebra ∷ Coalgebra (S.SqlF EJsonF) UnfoldableJC
jcCoalgebra = case _ of
S s → S.Ident s
I i → S.Literal (Integer 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 ∷ JS.JArray → 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 ∷ JS.JArray → L.List S.Sql
allFields =
L.fromFoldable ∘ F.foldMap (Set.fromFoldable ∘ allParents) ∘ fields
jarray ∷ JS.JArray
jarray =
map (unsafePartial fromRight ∘ jsonParser) jsonStrings
where
jsonStrings =
[ """{"foo": [{"bar": 1}, 12], "bar": {"baz": false}}"""
, """{"foo": true}"""
, """[12, null]"""
]
testSuite ∷ ∀ e. TestSuite e
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
Assert.equal expected $ 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
Assert.equal expectedFields 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
Assert.equal expected $ 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
Assert.equal expectedFields actualFields