#!/usr/bin/env tclsh set testdir [file dirname $argv0] source $testdir/tester.tcl do_execsql_test json5-ecma-script-1 { select json('{a:5,b:6}') ; } {{{"a":5,"b":6}}} do_execsql_test json5-ecma-script-2 { SELECT json('{ MNO_123$xyz : 789 }'); } {{{"MNO_123$xyz":789}}} do_execsql_test json5-with-single-trailing-comma-valid { select json('{"a":5, "b":6, }'); } {{{"a":5,"b":6}}} do_execsql_test json5-single-quoted { SELECT json('{"a": ''abcd''}'); } {{{"a":"abcd"}}} do_execsql_test json5-hexadecimal-1 { SELECT json('{a: 0x0}') } {{{"a":0}}} do_execsql_test json5-hexadecimal-2 { SELECT json('{a: 0xabcdef}') } {{{"a":11259375}}} do_execsql_test json5-hexadecimal-2 { SELECT json('{a: -0xabcdef}') } {{{"a":-11259375}}} do_execsql_test json5-number-1 { SELECT json('{x: 4.}') } {{{"x":4.0}}} do_execsql_test json5-number-2 { SELECT json('{x: +4.}') } {{{"x":4.0}}} do_execsql_test json5-number-3 { SELECT json('{x: -4.}') } {{{"x":-4.0}}} do_execsql_test json5-number-5 { SELECT json('{x: Infinity}') } {{{"x":9e999}}} do_execsql_test json5-number-6 { SELECT json('{x: -Infinity}') } {{{"x":-9e999}}} do_execsql_test json5-multi-comment { SELECT json(' /* abc */ { /*def*/ aaa /* xyz */ : // to the end of line 123 /* xyz */ , /* 123 */ }') } {{{"aaa":123}}} do_execsql_test json_array_str { SELECT json_array('a') } {{["a"]}} do_execsql_test json_array_numbers { SELECT json_array(1, 1.5) } {{[1,1.5]}} do_execsql_test json_array_numbers_2 { SELECT json_array(1., +2., -2.) } {{[1.0,2.0,-2.0]}} do_execsql_test json_array_null { SELECT json_array(null) } {{[null]}} do_execsql_test json_array_not_json { SELECT json_array('{"a":1}') } {{["{\"a\":1}"]}} do_execsql_test json_array_json { SELECT json_array(json('{"a":1}')) } {{[{"a":1}]}} do_execsql_test json_array_nested { SELECT json_array(json_array(1,2,3), json('[1,2,3]'), '[1,2,3]') } {{[[1,2,3],[1,2,3],"[1,2,3]"]}} do_execsql_test json_extract_null { SELECT json_extract(null, '$') } {{}} do_execsql_test json_extract_json_null_type { SELECT typeof(json_extract('null', '$')) } {{null}} do_execsql_test json_arrow_json_null_type { SELECT typeof('null' -> '$') } {{text}} do_execsql_test json_arrow_shift_json_null_type { SELECT typeof('null' ->> '$') } {{null}} do_execsql_test json_extract_empty { SELECT json_extract() } {{}} do_execsql_test json_extract_single_param { SELECT json_extract(1) } {{}} do_execsql_test json_extract_null_invalid_path { SELECT json_extract(null, 1) } {{}} do_execsql_test json_extract_null_invalid_path_2 { SELECT json_extract(null, CAST(1 AS BLOB)) } {{}} do_execsql_test json_extract_multiple_nulls { SELECT json_extract(null, CAST(1 AS BLOB), null, 1, 2, 3) } {{}} do_execsql_test json_extract_number { SELECT json_extract(1, '$') } {{1}} do_execsql_test json_extract_number_type { SELECT typeof(json_extract(1, '$')) } {{integer}} do_execsql_test json_arrow_number { SELECT 1 -> '$' } {{1}} do_execsql_test json_arrow_number_type { SELECT typeof(1 -> '$') } {{text}} do_execsql_test json_arrow_shift_number { SELECT 1 -> '$' } {{1}} do_execsql_test json_arrow_shift_number_type { SELECT typeof(1 ->> '$') } {{integer}} do_execsql_test json_extract_object_1 { SELECT json_extract('{"a": [1,2,3]}', '$.a') } {{[1,2,3]}} do_execsql_test json_arrow_object { SELECT '{"a": [1,2,3]}' -> '$.a' } {{[1,2,3]}} do_execsql_test json_arrow_shift_object { SELECT '{"a": [1,2,3]}' ->> '$.a' } {{[1,2,3]}} do_execsql_test json_extract_object_2 { SELECT json_extract('{"a": [1,2,3]}', '$.a', '$.a[0]', '$.a[1]', '$.a[3]') } {{[[1,2,3],1,2,null]}} do_execsql_test json_extract_object_3 { SELECT json_extract('{"a": [1,2,3]}', '$.a', '$.a[0]', '$.a[1]', null, '$.a[3]') } {{}} # TODO: fix me - this passes on SQLite and needs to be fixed in Limbo. # \x61 is the ASCII code for 'a' # do_execsql_test json_extract_with_escaping { # SELECT json_extract('{"\x61": 1}', '$.a') # } {{1}} # TODO: fix me - this passes on SQLite and needs to be fixed in Limbo. #do_execsql_test json_extract_with_escaping_2 { # SELECT json_extract('{"\x61": 1}', '$.\x61') #} {{1}} do_execsql_test json_extract_null_path { SELECT json_extract(1, null) } {{}} do_execsql_test json_arrow_null_path { SELECT 1 -> null } {{}} do_execsql_test json_arrow_shift_null_path { SELECT 1 ->> null } {{}} do_execsql_test json_extract_float { SELECT typeof(json_extract(1.0, '$')) } {{real}} do_execsql_test json_arrow_float { SELECT typeof(1.0 -> '$') } {{text}} do_execsql_test json_arrow_shift_float { SELECT typeof(1.0 ->> '$') } {{real}} do_execsql_test json_extract_true { SELECT json_extract('true', '$') } {{1}} do_execsql_test json_extract_true_type { SELECT typeof(json_extract('true', '$')) } {{integer}} do_execsql_test json_arrow_true { SELECT 'true' -> '$' } {{true}} do_execsql_test json_arrow_true_type { SELECT typeof('true' -> '$') } {{text}} do_execsql_test json_arrow_shift_true { SELECT 'true' ->> '$' } {{1}} do_execsql_test json_arrow_shift_true_type { SELECT typeof('true' ->> '$') } {{integer}} do_execsql_test json_extract_false { SELECT json_extract('false', '$') } {{0}} do_execsql_test json_extract_false_type { SELECT typeof(json_extract('false', '$')) } {{integer}} do_execsql_test json_arrow_false { SELECT 'false' -> '$' } {{false}} do_execsql_test json_arrow_false_type { SELECT typeof('false' -> '$') } {{text}} do_execsql_test json_arrow_shift_false { SELECT 'false' ->> '$' } {{0}} do_execsql_test json_arrow_shift_false_type { SELECT typeof('false' ->> '$') } {{integer}} do_execsql_test json_extract_string { SELECT json_extract('"string"', '$') } {{string}} do_execsql_test json_extract_string_type { SELECT typeof(json_extract('"string"', '$')) } {{text}} do_execsql_test json_arrow_string { SELECT '"string"' -> '$' } {{"string"}} do_execsql_test json_arrow_string_type { SELECT typeof('"string"' -> '$') } {{text}} do_execsql_test json_arrow_shift_string { SELECT '"string"' ->> '$' } {{string}} do_execsql_test json_arrow_shift_string_type { SELECT typeof('"string"' ->> '$') } {{text}} do_execsql_test json_arrow_implicit_root_path { SELECT '{"a":1}' -> 'a'; } {{1}} do_execsql_test json_arrow_shift_implicit_root_path { SELECT '{"a":1}' ->> 'a'; } {{1}} # TODO: fix me after rebasing on top of https://github.com/tursodatabase/limbo/pull/631 - use the Option value in json_extract_single #do_execsql_test json_arrow_implicit_root_path_undefined_key { # SELECT '{"a":1}' -> 'x'; #} {{}} do_execsql_test json_arrow_shift_implicit_root_path_undefined_key { SELECT '{"a":1}' ->> 'x'; } {{}} do_execsql_test json_arrow_implicit_root_path_array { SELECT '[1,2,3]' -> 1; } {{2}} do_execsql_test json_arrow_shift_implicit_root_path_array { SELECT '[1,2,3]' ->> 1; } {{2}} do_execsql_test json_arrow_implicit_root_path_array_negative_idx { SELECT '[1,2,3]' -> -1; } {{3}} do_execsql_test json_arrow_shift_implicit_root_path_array_negative_idx { SELECT '[1,2,3]' ->> -1; } {{3}} do_execsql_test json_arrow_implicit_real_cast { SELECT '{"1.5":"abc"}' -> 1.5; } {{"abc"}} do_execsql_test json_arrow_shift_implicit_real_cast { SELECT '{"1.5":"abc"}' -> 1.5; } {{"abc"}} do_execsql_test json_arrow_implicit_true_cast { SELECT '[1,2,3]' -> true } {{2}} do_execsql_test json_arrow_shift_implicit_true_cast { SELECT '[1,2,3]' ->> true } {{2}} do_execsql_test json_arrow_implicit_false_cast { SELECT '[1,2,3]' -> false } {{1}} do_execsql_test json_arrow_shift_implicit_false_cast { SELECT '[1,2,3]' ->> false } {{1}} do_execsql_test json_arrow_chained { select '{"a":2,"c":[4,5,{"f":7}]}' -> 'c' -> 2 ->> 'f' } {{7}} # TODO: fix me - this passes on SQLite and needs to be fixed in Limbo. do_execsql_test json_extract_multiple_null_paths { SELECT json_extract(1, null, null, null) } {{}} do_execsql_test json_extract_array { SELECT json_extract('[1,2,3]', '$') } {{[1,2,3]}} do_execsql_test json_arrow_array { SELECT '[1,2,3]' -> '$' } {{[1,2,3]}} do_execsql_test json_arrow_shift_array { SELECT '[1,2,3]' ->> '$' } {{[1,2,3]}} # TODO: fix me - this passes on SQLite and needs to be fixed in Limbo. #do_execsql_test json_extract_quote { # SELECT json_extract('{"\"":1 }', '$.\"') #} {{1}} # Overflows 2**32 is equivalent to 0 do_execsql_test json_extract_overflow_int32_1 { SELECT json_extract('[1,2,3]', '$[4294967296]') } {{1}} # Overflows 2**32 + 1 is equivalent to 1 do_execsql_test json_extract_overflow_int32_2 { SELECT json_extract('[1,2,3]', '$[4294967297]') } {{2}} # Overflows -2**32 - 1 is equivalent to -1 do_execsql_test json_extract_overflow_int32_3 { SELECT json_extract('[1,2,3]', '$[#-4294967297]') } {{3}} # Overflows -2**32 - 2 is equivalent to -2 do_execsql_test json_extract_overflow_int32_3 { SELECT json_extract('[1,2,3]', '$[#-4294967298]') } {{2}} # pow(2,63) + 1 == 9223372036854775808 do_execsql_test json_extract_overflow_int64 { SELECT json_extract('[1,2,3]', '$[9223372036854775808]'); } {{1}} # TODO: fix me - this passes on SQLite and needs to be fixed in Limbo. # pow(2, 127) + 1 == 170141183460469231731687303715884105729 #do_execsql_test json_extract_overflow_int128 { # SELECT json_extract('[1, 2, 3]', '$[170141183460469231731687303715884105729]'); #} {{2}} # TODO: fix me - this passes on SQLite and needs to be fixed in Limbo. #do_execsql_test json_extract_blob { # select json_extract(CAST('[1,2,3]' as BLOB), '$[1]') #} {{2}} do_execsql_test json_array_length { SELECT json_array_length('[1,2,3,4]'); } {{4}} do_execsql_test json_array_length_empty { SELECT json_array_length('[]'); } {{0}} do_execsql_test json_array_length_root { SELECT json_array_length('[1,2,3,4]', '$'); } {{4}} do_execsql_test json_array_length_not_array { SELECT json_array_length('{"one":[1,2,3]}'); } {{0}} do_execsql_test json_array_length_via_prop { SELECT json_array_length('{"one":[1,2,3]}', '$.one'); } {{3}} do_execsql_test json_array_length_via_index { SELECT json_array_length('[[1,2,3,4]]', '$[0]'); } {{4}} do_execsql_test json_array_length_via_index_not_array { SELECT json_array_length('[1,2,3,4]', '$[2]'); } {{0}} do_execsql_test json_array_length_via_bad_prop { SELECT json_array_length('{"one":[1,2,3]}', '$.two'); } {{}} do_execsql_test json_array_length_nested { SELECT json_array_length('{"one":[[1,2,3],2,3]}', '$.one[0]'); } {{3}} do_execsql_test json_type_no_path { select json_type('{"a":[2,3.5,true,false,null,"x"]}') } {{object}} do_execsql_test json_type_root_path { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$') } {{object}} do_execsql_test json_type_array { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a') } {{array}} do_execsql_test json_type_integer { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]') } {{integer}} do_execsql_test json_type_real { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]') } {{real}} do_execsql_test json_type_true { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]') } {{true}} do_execsql_test json_type_false { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]') } {{false}} do_execsql_test json_type_null { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]') } {{null}} do_execsql_test json_type_text { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]') } {{text}} do_execsql_test json_type_NULL { select json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]') } {{}} do_execsql_test json_type_cast { select json_type(1) } {{integer}} do_execsql_test json_type_null_arg { select json_type(null) } {{}} do_execsql_test json_error_position_valid { SELECT json_error_position('{"a":55,"b":72,}'); } {{0}} do_execsql_test json_error_position_valid_ws { SELECT json_error_position('{"a":55,"b":72 , }'); } {{0}} do_execsql_test json_error_position_object { SELECT json_error_position('{"a":55,"b":72,,}'); } {{16}} do_execsql_test json_error_position_array_valid { SELECT json_error_position('["a",55,"b",72,]'); } {{0}} do_execsql_test json_error_position_array_valid_ws { SELECT json_error_position('["a",55,"b",72 , ]'); } {{0}} do_execsql_test json_error_position_array { SELECT json_error_position('["a",55,"b",72,,]'); } {{16}} do_execsql_test json_error_position_null { SELECT json_error_position(NULL); } {{}} do_execsql_test json_error_position_complex { SELECT json_error_position('{a:null,{"h":[1,[1,2,3]],"j":"abc"}:true}'); } {{9}} do_execsql_test json_object_simple { SELECT json_object('key', 'value'); } {{{"key":"value"}}} do_execsql_test json_object_nested { SELECT json_object('grandparent',json_object('parent', json_object('child', 'value'))); } {{{"grandparent":{"parent":{"child":"value"}}}}} do_execsql_test json_object_quoted_json { SELECT json_object('parent', '{"child":"value"}'); } {{{"parent":"{\"child\":\"value\"}"}}} do_execsql_test json_object_unquoted_json { SELECT json_object('parent', json('{"child":"value"}')); } {{{"parent":{"child":"value"}}}} do_execsql_test json_object_multiple_values { SELECT json_object('text', 'value', 'json', json_object('key', 'value'), 'int', 1, 'float', 1.5, 'null', null); } {{{"text":"value","json":{"key":"value"},"int":1,"float":1.5,"null":null}}} do_execsql_test json_object_empty { SELECT json_object(); } {{{}}} do_execsql_test json_object_json_array { SELECT json_object('ex',json('[52,3]')); } {{{"ex":[52,3]}}} do_execsql_test json_from_json_object { SELECT json(json_object('key','value')); } {{{"key":"value"}}} # FIXME: this behaviour differs from sqlite. Although, sqlite docs states # that this could change in a "future enhancement" (https://www.sqlite.org/json1.html#jobj) #do_execsql_test json_object_duplicated_keys { # SELECT json_object('key', 'value', 'key', 'value2'); #} {{{"key":"value2"}}} # do_execsql_test json_valid_1 { SELECT json_valid('{"a":55,"b":72}'); } {1} do_execsql_test json_valid_2 { SELECT json_valid('["a",55,"b",72]'); } {1} do_execsql_test json_valid_3 { SELECT json_valid( CAST('{"a":1}' AS BLOB) ); } {1} do_execsql_test json_valid_4 { SELECT json_valid(123); } {1} do_execsql_test json_valid_5 { SELECT json_valid(12.3); } {1} do_execsql_test json_valid_6 { SELECT json_valid('not a valid json'); } {0} do_execsql_test json_valid_7 { SELECT json_valid('{"a":"55,"b":72}'); } {0} do_execsql_test json_valid_8 { SELECT json_valid('{"a":55 "b":72}'); } {0} do_execsql_test json_valid_3 { SELECT json_valid( CAST('{"a":"1}' AS BLOB) ); } {0} do_execsql_test json_valid_9 { SELECT json_valid(NULL); } {}