3 # The author disclaims copyright to this source code. In place of
4 # a legal notice, here is a blessing:
6 # May you do good and not evil.
7 # May you find forgiveness for yourself and forgive others.
8 # May you share freely, never taking more than you give.
10 #***********************************************************************
11 # This file implements tests for JSON SQL functions extension to the
14 # This file contains tests automatically generated from the json1
18 set testdir [file dirname $argv0]
19 source $testdir/tester.tcl
21 do_execsql_test json102-100 {
22 SELECT json_object('ex','[52,3.14159]');
23 } {{{"ex":"[52,3.14159]"}}}
24 do_execsql_test json102-110 {
25 SELECT json_object('ex',json('[52,3.14159]'));
26 } {{{"ex":[52,3.14159]}}}
27 do_execsql_test json102-120 {
28 SELECT json_object('ex',json_array(52,3.14159));
29 } {{{"ex":[52,3.14159]}}}
30 do_execsql_test json102-130 {
31 SELECT json(' { "this" : "is", "a": [ "test" ] } ');
32 } {{{"this":"is","a":["test"]}}}
33 do_execsql_test json102-140 {
34 SELECT json_array(1,2,'3',4);
36 do_execsql_test json102-150 {
37 SELECT json_array('[1,2]');
39 do_execsql_test json102-160 {
40 SELECT json_array(json_array(1,2));
42 do_execsql_test json102-170 {
43 SELECT json_array(1,null,'3','[4,5]','{"six":7.7}');
44 } {{[1,null,"3","[4,5]","{\"six\":7.7}"]}}
45 do_execsql_test json102-180 {
46 SELECT json_array(1,null,'3',json('[4,5]'),json('{"six":7.7}'));
47 } {{[1,null,"3",[4,5],{"six":7.7}]}}
48 do_execsql_test json102-190 {
49 SELECT json_array_length('[1,2,3,4]');
51 do_execsql_test json102-191 {
52 SELECT json_array_length( json_remove('[1,2,3,4]','$[2]') );
54 do_execsql_test json102-200 {
55 SELECT json_array_length('[1,2,3,4]', '$');
57 do_execsql_test json102-210 {
58 SELECT json_array_length('[1,2,3,4]', '$[2]');
60 do_execsql_test json102-220 {
61 SELECT json_array_length('{"one":[1,2,3]}');
63 do_execsql_test json102-230 {
64 SELECT json_array_length('{"one":[1,2,3]}', '$.one');
66 do_execsql_test json102-240 {
67 SELECT json_array_length('{"one":[1,2,3]}', '$.two');
69 do_execsql_test json102-250 {
70 SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$');
71 } {{{"a":2,"c":[4,5,{"f":7}]}}}
72 do_execsql_test json102-260 {
73 SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c');
75 do_execsql_test json102-270 {
76 SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]');
78 do_execsql_test json102-280 {
79 SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f');
81 do_execsql_test json102-290 {
82 SELECT json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a');
84 do_execsql_test json102-300 {
85 SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x');
87 do_execsql_test json102-310 {
88 SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x', '$.a');
90 do_execsql_test json102-320 {
91 SELECT json_insert('{"a":2,"c":4}', '$.a', 99);
93 do_execsql_test json102-330 {
94 SELECT json_insert('{"a":2,"c":4}', '$.e', 99);
95 } {{{"a":2,"c":4,"e":99}}}
96 do_execsql_test json102-340 {
97 SELECT json_replace('{"a":2,"c":4}', '$.a', 99);
99 do_execsql_test json102-350 {
100 SELECT json_replace('{"a":2,"c":4}', '$.e', 99);
102 do_execsql_test json102-360 {
103 SELECT json_set('{"a":2,"c":4}', '$.a', 99);
105 do_execsql_test json102-370 {
106 SELECT json_set('{"a":2,"c":4}', '$.e', 99);
107 } {{{"a":2,"c":4,"e":99}}}
108 do_execsql_test json102-380 {
109 SELECT json_set('{"a":2,"c":4}', '$.c', '[97,96]');
110 } {{{"a":2,"c":"[97,96]"}}}
111 do_execsql_test json102-390 {
112 SELECT json_set('{"a":2,"c":4}', '$.c', json('[97,96]'));
113 } {{{"a":2,"c":[97,96]}}}
114 do_execsql_test json102-400 {
115 SELECT json_set('{"a":2,"c":4}', '$.c', json_array(97,96));
116 } {{{"a":2,"c":[97,96]}}}
117 do_execsql_test json102-410 {
118 SELECT json_object('a',2,'c',4);
120 do_execsql_test json102-420 {
121 SELECT json_object('a',2,'c','{e:5}');
122 } {{{"a":2,"c":"{e:5}"}}}
123 do_execsql_test json102-430 {
124 SELECT json_object('a',2,'c',json_object('e',5));
125 } {{{"a":2,"c":{"e":5}}}}
126 do_execsql_test json102-440 {
127 SELECT json_remove('[0,1,2,3,4]','$[2]');
129 do_execsql_test json102-450 {
130 SELECT json_remove('[0,1,2,3,4]','$[2]','$[0]');
132 do_execsql_test json102-460 {
133 SELECT json_remove('[0,1,2,3,4]','$[0]','$[2]');
135 do_execsql_test json102-470 {
136 SELECT json_remove('{"x":25,"y":42}');
137 } {{{"x":25,"y":42}}}
138 do_execsql_test json102-480 {
139 SELECT json_remove('{"x":25,"y":42}','$.z');
140 } {{{"x":25,"y":42}}}
141 do_execsql_test json102-490 {
142 SELECT json_remove('{"x":25,"y":42}','$.y');
144 do_execsql_test json102-500 {
145 SELECT json_remove('{"x":25,"y":42}','$');
147 do_execsql_test json102-510 {
148 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}');
150 do_execsql_test json102-520 {
151 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$');
153 do_execsql_test json102-530 {
154 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a');
156 do_execsql_test json102-540 {
157 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]');
159 do_execsql_test json102-550 {
160 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]');
162 do_execsql_test json102-560 {
163 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]');
165 do_execsql_test json102-570 {
166 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]');
168 do_execsql_test json102-580 {
169 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]');
171 do_execsql_test json102-590 {
172 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]');
174 do_execsql_test json102-600 {
175 SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]');
177 do_execsql_test json102-610 {
178 SELECT json_valid(char(123)||'"x":35'||char(125));
180 do_execsql_test json102-620 {
181 SELECT json_valid(char(123)||'"x":35');
185 do_execsql_test json102-1000 {
186 CREATE TABLE user(name,phone);
187 INSERT INTO user(name,phone) VALUES
188 ('Alice','["919-555-2345","804-555-3621"]'),
189 ('Bob','["201-555-8872"]'),
190 ('Cindy','["704-555-9983"]'),
191 ('Dave','["336-555-8421","704-555-4321","803-911-4421"]');
192 SELECT DISTINCT user.name
193 FROM user, json_each(user.phone)
194 WHERE json_each.value LIKE '704-%'
198 do_execsql_test json102-1010 {
200 SET phone=json_extract(phone,'$[0]')
201 WHERE json_array_length(phone)<2;
202 SELECT name, substr(phone,1,5) FROM user ORDER BY name;
203 } {Alice {["919} Bob 201-5 Cindy 704-5 Dave {["336}}
204 do_execsql_test json102-1011 {
205 SELECT name FROM user WHERE phone LIKE '704-%'
208 FROM user, json_each(user.phone)
209 WHERE json_valid(user.phone)
210 AND json_each.value LIKE '704-%';
213 do_execsql_test json102-1100 {
214 CREATE TABLE big(json JSON);
215 INSERT INTO big(json) VALUES('{
219 {"uuid":"bb108722-572e-11e5-9320-7f3b63a4ca74"},
220 {"uuid":"c690dc14-572e-11e5-95f9-dfc8861fd535"},
222 {"uuid":"6fa5181e-5721-11e5-a04e-57f3d7b32808"}
226 INSERT INTO big(json) VALUES('{
228 "stuff":["hello","world","xyzzy"],
231 {"uuid":"c690dc14-572e-11e5-95f9-dfc8861fd535"}
235 set correct_answer [list \
241 1 {$.partlist[0].uuid} bb108722-572e-11e5-9320-7f3b63a4ca74 \
242 1 {$.partlist[1].uuid} c690dc14-572e-11e5-95f9-dfc8861fd535 \
243 1 {$.partlist[2].subassembly[0].uuid} 6fa5181e-5721-11e5-a04e-57f3d7b32808 \
245 2 {$.stuff[0]} hello \
246 2 {$.stuff[1]} world \
247 2 {$.stuff[2]} xyzzy \
248 2 {$.partlist[0].uuid} 0 \
249 2 {$.partlist[1].uuid} c690dc14-572e-11e5-95f9-dfc8861fd535]
250 do_execsql_test json102-1110 {
251 SELECT big.rowid, fullkey, value
252 FROM big, json_tree(big.json)
253 WHERE json_tree.type NOT IN ('object','array')
254 ORDER BY +big.rowid, +json_tree.id
256 do_execsql_test json102-1120 {
257 SELECT big.rowid, fullkey, atom
258 FROM big, json_tree(big.json)
259 WHERE atom IS NOT NULL
260 ORDER BY +big.rowid, +json_tree.id
263 do_execsql_test json102-1130 {
264 SELECT DISTINCT json_extract(big.json,'$.id')
265 FROM big, json_tree(big.json,'$.partlist')
266 WHERE json_tree.key='uuid'
267 AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
269 do_execsql_test json102-1131 {
270 SELECT DISTINCT json_extract(big.json,'$.id')
271 FROM big, json_tree(big.json,'$')
272 WHERE json_tree.key='uuid'
273 AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
275 do_execsql_test json102-1132 {
276 SELECT DISTINCT json_extract(big.json,'$.id')
277 FROM big, json_tree(big.json)
278 WHERE json_tree.key='uuid'
279 AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
281 } ;# end ifcapable vtab
283 #-------------------------------------------------------------------------
284 # Test that json_valid() correctly identifies non-ascii range
285 # characters as non-whitespace.
287 do_execsql_test json102-1201 { SELECT json_valid(char(32) || '"xyz"') } 1
288 do_execsql_test json102-1202 { SELECT json_valid(char(200) || '"xyz"') } 0
290 # Off-by-one error in jsonAppendString()
292 for {set i 0} {$i<100} {incr i} {
293 set str abcdef[string repeat \" [expr {$i+50}]]uvwxyz
294 do_test json102-[format %d [expr {$i+1300}]] {
295 db eval {SELECT json_extract(json_array($::str),'$[0]')==$::str}
299 #-------------------------------------------------------------------------
300 # 2017-04-08 ticket b93be8729a895a528e2849fca99f7
301 # JSON extension accepts invalid numeric values
303 # JSON does not allow leading zeros. But the JSON extension was
304 # allowing them. The following tests verify that the problem is now
307 foreach {id j x0 x5} {
308 1401 {'{"x":01}'} 0 0
309 1402 {'{"x":-01}'} 0 0
311 1404 {'{"x":-0}'} 1 1
312 1405 {'{"x":0.1}'} 1 1
313 1406 {'{"x":-0.1}'} 1 1
314 1407 {'{"x":0.0000}'} 1 1
315 1408 {'{"x":-0.0000}'} 1 1
316 1409 {'{"x":01.5}'} 0 0
317 1410 {'{"x":-01.5}'} 0 0
318 1411 {'{"x":00}'} 0 0
319 1412 {'{"x":-00}'} 0 0
320 1413 {'{"x":+0}'} 0 1
321 1414 {'{"x":+5}'} 0 1
322 1415 {'{"x":+5.5}'} 0 1
324 do_execsql_test json102-$id "
325 SELECT json_valid($j), NOT json_error_position($j);
329 #------------------------------------------------------------------------
330 # 2017-04-10 ticket 6c9b5514077fed34551f98e64c09a10dc2fc8e16
331 # JSON extension accepts strings containing control characters.
333 # The JSON spec requires that all control characters be escaped.
335 do_execsql_test json102-1500 {
336 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<0x20)
337 SELECT x FROM c WHERE json_valid(printf('{"a":"x%sz"}', char(x))) ORDER BY x;
340 # All control characters are escaped
342 do_execsql_test json102-1501 {
343 WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<0x1f)
344 SELECT sum(json_valid(json_quote('a'||char(x)||'z'))) FROM c ORDER BY x;
347 # 2022-01-10 tests for -> and ->> operators
350 do_execsql_test json102-1600 {
351 CREATE TABLE t1(id INTEGER PRIMARY KEY, x JSON);
352 INSERT INTO t1(id,x) VALUES
358 (6, '{"a":{"b":9}}'),
363 CASE WHEN subtype(x->'a') THEN 'json' ELSE typeof(x->'a') END AS 'type',
365 CASE WHEN subtype(x->>'a') THEN 'json' ELSE typeof(x->>'a') END AS 'type',
366 json_extract(x,'$.a') AS 'json_extract',
367 CASE WHEN subtype(json_extract(x,'$.a'))
368 THEN 'json' ELSE typeof(json_extract(x,'$.a')) END AS 'type'
371 1 null json {} null {} null \
372 2 123 json 123 integer 123 integer \
373 3 4.5 json 4.5 real 4.5 real \
374 4 {"six"} json six text six text \
375 5 {[7,8]} json {[7,8]} text {[7,8]} json \
376 6 {{"b":9}} json {{"b":9}} text {{"b":9}} json \
377 7 {} null {} null {} null
379 do_execsql_test json102-1610 {
381 INSERT INTO t1(x) VALUES('[null,123,4.5,"six",[7,8],{"b":9}]');
382 WITH c(y) AS (VALUES(0),(1),(2),(3),(4),(5),(6))
386 CASE WHEN subtype(x->y) THEN 'json' ELSE typeof(x->y) END AS 'type',
388 CASE WHEN subtype(x->>y) THEN 'json' ELSE typeof(x->>y) END AS 'type',
389 json_extract(x,format('$[%d]',y)) AS 'json_extract',
390 CASE WHEN subtype(json_extract(x,format('$[%d]',y)))
391 THEN 'json' ELSE typeof(json_extract(x,format('$[%d]',y))) END AS 'type'
392 FROM c, t1 ORDER BY y;
394 0 null json {} null {} null \
395 1 123 json 123 integer 123 integer \
396 2 4.5 json 4.5 real 4.5 real \
397 3 {"six"} json six text six text \
398 4 {[7,8]} json {[7,8]} text {[7,8]} json \
399 5 {{"b":9}} json {{"b":9}} text {{"b":9}} json \
400 6 {} null {} null {} null
404 do_execsql_test json102-1700 {
405 CREATE TABLE t1(a1 DATE, a2 INTEGER PRIMARY KEY, a3 INTEGER, memo TEXT);
406 CREATE INDEX t1x1 ON t1(a3, a1, memo->>'y');
407 INSERT INTO t1(a2,a1,a3,memo) VALUES (876, '2023-08-03', 5, '{"x":77,"y":4}');
409 do_execsql_test json102-1710 {
410 UPDATE t1 SET memo = JSON_REMOVE(memo, '$.y');
411 PRAGMA integrity_check;
413 } {ok 2023-08-03 876 5 {{"x":77}}}
414 do_execsql_test json102-1720 {
415 UPDATE t1 SET memo = JSON_SET(memo, '$.y', 6)
416 WHERE a2 IN (876) AND JSON_TYPE(memo, '$.y') IS NULL;
417 PRAGMA integrity_check;
419 } {ok 2023-08-03 876 5 {{"x":77,"y":6}}}