Skip to content

Commit 8672c6e

Browse files
committed
Start docs on native PG JSON(B) support compared to EQL
1 parent 9d8e6fe commit 8672c6e

File tree

1 file changed

+308
-0
lines changed

1 file changed

+308
-0
lines changed
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
# Native Postgres JSON(B) Compared to EQL
2+
3+
EQL supports a subset of functionality supported by the native Postgres JSON(B) functions and operators. The following examples compare natiive Postres JSON(B) functions and operators to the related functionality in EQL.
4+
5+
## `json ->> text``text` and `json -> text``jsonb`/`json`
6+
7+
### Native Postgres JSON(B)
8+
9+
```sql
10+
-- `->` (returns JSON(B))
11+
SELECT plaintext_jsonb->'field_a' FROM examples;
12+
13+
-- `->>` (returns text)
14+
SELECT plaintext_jsonb->>'field_a' FROM examples;
15+
```
16+
17+
### EQL
18+
19+
EQL JSONB functions accept an eJSONPath as an argument (instead of using `->`/`->>`) for lookups.
20+
21+
#### Decryption example
22+
23+
`cs_ste_vec_value_v1` returns the Plaintext EQL payload to the client.
24+
25+
```sql
26+
SELECT cs_ste_vec_value_v1(encrypted_jsonb, $1) FROM examples;
27+
```
28+
29+
```javascript
30+
// Assume that examples.encrypted_jsonb has JSON objects with
31+
// the shape:
32+
{
33+
"field_a": 100
34+
}
35+
36+
// `$1` is the EQL plaintext payload for the eJSONPath `$.field_a`:
37+
{
38+
"k": "pt",
39+
"p": "$.field_a",
40+
"i": {
41+
"t": "examples",
42+
"c": "encrypted_jsonb"
43+
},
44+
"v": 1,
45+
"q": "ejson_path"
46+
}
47+
```
48+
49+
#### Comparison example
50+
51+
`cs_ste_vec_term_v1` returns an ORE term for comparison.
52+
53+
```sql
54+
SELECT * FROM examples
55+
WHERE cs_ste_vec_term_v1(examples.encrypted_jsonb, $1) > cs_ste_vec_term_v1($2)
56+
```
57+
58+
```javascript
59+
// Assume that examples.encrypted_jsonb has JSON objects with
60+
// the shape:
61+
{
62+
"field_a": 100
63+
}
64+
65+
// `$1` is the EQL plaintext payload for the eJSONPath `$.field_a`:
66+
{
67+
"k": "pt",
68+
"p": "$.field_a",
69+
"i": {
70+
"t": "examples",
71+
"c": "encrypted_jsonb"
72+
},
73+
"v": 1,
74+
"q": "ejson_path"
75+
}
76+
77+
// `$2` is the EQL plaintext payload for the ORE term to compare against:
78+
{
79+
"k": "pt",
80+
"p": "123",
81+
"i": {
82+
"t": "examples",
83+
"c": "encrypted_jsonb"
84+
},
85+
"v": 1,
86+
"q": "ste_vec"
87+
}
88+
```
89+
90+
#### Containment example
91+
92+
TODO: do we want containment examples for these, too?
93+
94+
## `json #>> text[]``text` and `json #> text[]``jsonb`/`json`
95+
96+
### Native Postgres JSON(B)
97+
98+
```sql
99+
-- `#>` (returns JSON(B))
100+
SELECT plaintext_jsonb#>'{field_a,field_b}' FROM examples;
101+
102+
-- `#>>` (returns text)
103+
SELECT plaintext_jsonb#>>'{field_a,field_b}' FROM examples;
104+
```
105+
106+
### EQL
107+
108+
EQL JSONB functions accept an eJSONPath as an argument (instead of using `#>`/`#>>`) for lookups.
109+
110+
Note that these are similar to the examples for `->`/`->>`. The difference in these examples is that the path does a lookup multiple levels deep.
111+
112+
#### Decryption example
113+
114+
`cs_ste_vec_value_v1` returns the Plaintext EQL payload to the client.
115+
116+
```sql
117+
SELECT cs_ste_vec_value_v1(encrypted_jsonb, $1) FROM examples;
118+
```
119+
120+
```javascript
121+
// Assume that examples.encrypted_jsonb has JSON objects with
122+
// the shape:
123+
{
124+
"field_a": {
125+
"field_b": 100
126+
}
127+
}
128+
129+
// `$1` is the EQL plaintext payload for the eJSONPath `$.field_a.field_b`:
130+
{
131+
"k": "pt",
132+
"p": "$.field_a.field_b",
133+
"i": {
134+
"t": "examples",
135+
"c": "encrypted_jsonb"
136+
},
137+
"v": 1,
138+
"q": "ejson_path"
139+
}
140+
```
141+
142+
#### Comparison example
143+
144+
`cs_ste_vec_term_v1` returns an ORE term for comparison.
145+
146+
```sql
147+
SELECT * FROM examples
148+
WHERE cs_ste_vec_term_v1(examples.encrypted_jsonb, $1) > cs_ste_vec_term_v1($2)
149+
```
150+
151+
```javascript
152+
// Assume that examples.encrypted_jsonb has JSON objects with
153+
// the shape:
154+
{
155+
"field_a": {
156+
"field_b": 100
157+
}
158+
}
159+
160+
// `$1` is the EQL plaintext payload for the eJSONPath `$.field_a.field_b`:
161+
{
162+
"k": "pt",
163+
"p": "$.field_a.field_b",
164+
"i": {
165+
"t": "examples",
166+
"c": "encrypted_jsonb"
167+
},
168+
"v": 1,
169+
"q": "ejson_path"
170+
}
171+
172+
// `$2` is the EQL plaintext payload for the ORE term to compare against:
173+
{
174+
"k": "pt",
175+
"p": "123",
176+
"i": {
177+
"t": "examples",
178+
"c": "encrypted_jsonb"
179+
},
180+
"v": 1,
181+
"q": "ste_vec"
182+
}
183+
```
184+
185+
#### Containment example
186+
187+
TODO: do we want containment examples for these, too?
188+
189+
## `json_array_elements`, `jsonb_array_elements`, `json_array_elements_text`, and `jsonb_array_elements_text`
190+
191+
### Native Postgres JSON(B)
192+
193+
```sql
194+
-- Each returns the results...
195+
--
196+
-- Value
197+
-- _____
198+
-- a
199+
-- b
200+
--
201+
-- The only difference is that the input is either json or jsonb (depending
202+
-- on the prefix of the function name) and the output is either json,
203+
-- jsonb, or text (depending on both the prefix and the suffix).
204+
205+
SELECT * from json_array_elements('["a", "b"]');
206+
SELECT * from jsonb_array_elements('["a", "b"]');
207+
SELECT * from json_array_elements_text('["a", "b"]');
208+
SELECT * from jsonb_array_elements_text('["a", "b"]');
209+
```
210+
211+
### EQL
212+
213+
#### Decryption example
214+
215+
EQL currently doesn't support returning a `SETOF` values for decryption (for returning a row per item in an array), but `cs_ste_vec_value_v1` can be used to return an array to the client to process.
216+
217+
The query...
218+
219+
```sql
220+
SELECT cs_ste_vec_value_v1(encrypted_jsonb, $1) AS val FROM examples;
221+
```
222+
223+
With the params...
224+
225+
```javascript
226+
// Assume that examples.encrypted_jsonb has JSON objects with
227+
// the shape:
228+
{
229+
"field_a": [1, 2, 3]
230+
}
231+
232+
// `$1` is the EQL plaintext payload for the eJSONPath `$.field_a`:
233+
{
234+
"k": "pt",
235+
"p": "$.field_a",
236+
"i": {
237+
"t": "examples",
238+
"c": "encrypted_jsonb"
239+
},
240+
"v": 1,
241+
"q": "ejson_path"
242+
}
243+
```
244+
245+
Would return the EQL plaintext payload with an array (`[1, 2, 3]` for example):
246+
247+
```javascript
248+
// Example result for a single row
249+
{
250+
"k": "pt",
251+
"p": "[1, 2, 3]",
252+
"i": {
253+
"t": "examples",
254+
"c": "encrypted_jsonb"
255+
},
256+
"v": 1,
257+
"q": null
258+
}
259+
```
260+
261+
#### Comparison example
262+
263+
`cs_ste_vec_terms_v1` (note that terms is plural) can be used to return an array of ORE terms for comparison. The array can be `unnest`ed to work with a `SETOF` ORE terms for comparison.
264+
265+
The eJSONPath used with `cs_ste_vec_terms_v1` needs to end with `[*]` (`$.some_array_field[*]` for example).
266+
267+
Example query:
268+
269+
```sql
270+
SELECT id FROM examples e
271+
WHERE EXISTS (
272+
SELECT 1
273+
FROM unnest(cs_ste_vec_terms_v1(e.encrypted_jsonb, $1)) AS term
274+
WHERE term > cs_ste_vec_term_v1($2)
275+
);
276+
```
277+
278+
```javascript
279+
// Assume that examples.encrypted_jsonb has JSON objects with
280+
// the shape:
281+
{
282+
"field_a": [1, 2, 3]
283+
}
284+
285+
// `$1` is the EQL plaintext payload for the eJSONPath `$.field_a[*]`:
286+
{
287+
"k": "pt",
288+
"p": "$.field_a[*]",
289+
"i": {
290+
"t": "examples",
291+
"c": "encrypted_jsonb"
292+
},
293+
"v": 1,
294+
"q": "ejson_path"
295+
}
296+
297+
// `$2` is the EQL plaintext payload for the ORE term to compare against:
298+
{
299+
"k": "pt",
300+
"p": "2",
301+
"i": {
302+
"t": "examples",
303+
"c": "encrypted_jsonb"
304+
},
305+
"v": 1,
306+
"q": "ste_vec"
307+
}
308+
```

0 commit comments

Comments
 (0)