]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Test cases added, and some bugs fixed.
authordrh <>
Thu, 27 Apr 2023 23:29:09 +0000 (23:29 +0000)
committerdrh <>
Thu, 27 Apr 2023 23:29:09 +0000 (23:29 +0000)
FossilOrigin-Name: bc84a82e4ddc1b71025c56c49e62a44f0b12fa87a6417ad61967d9d3121a0d4e

manifest
manifest.uuid
src/json.c
test/json501.test [new file with mode: 0644]

index a630d6827fe1eb1d122f22be410a3ce39ba9789d..dcbc60c91ca6fd4cc86e015205c6822bbe568a21 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Further\soptimizations\sto\sthe\sJSON\sparser.
-D 2023-04-27T19:30:53.107
+C Test\scases\sadded,\sand\ssome\sbugs\sfixed.
+D 2023-04-27T23:29:09.447
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -592,7 +592,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
 F src/hwtime.h b638809e083b601b618df877b2e89cb87c2a47a01f4def10be4c4ebb54664ac7
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c a8de1db43335fc4946370a7a7e47d89975ad678ddb15078a150e993ba2fb37d4
-F src/json.c 1c1cc509dd866dc05973eea6bd390c318c57fdad63c239ed3e2d214f78560dd5
+F src/json.c 76c7d11f7a5f29eaf3180c6ffcdf7fa808e931f519295d0725a736be8956a5cd
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c be5af440f3192c58681b5d43167dbca3ccbfce394d89faa22378a14264781136
 F src/main.c 09bc5191f75dc48fc4dfddda143cb864c0c3dbc3297eb9a9c8e01fea58ff847d
@@ -1258,6 +1258,7 @@ F test/json102.test 1f61f469d763ff26430dbee76bc75e0aa73084ca84f10e58744fdb899e56
 F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
 F test/json104.test a502dc01853aada95d721b3b275afbe2dc18fffdac1fea6e96fb20c13586bbb5
 F test/json105.test 11670a4387f4308ae0318cadcbd6a918ea7edcd19fbafde020720a073952675d
+F test/json501.test 43614faefc9ac708e29d55cdc290b5cea336c151030196885708ea3d132fce63
 F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
 F test/kvtest.c feb4358fb022da8ebd098c45811f2f6507688bb6c43aa72b3e840df19026317b
 F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
@@ -2063,8 +2064,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 58398292e8473b0b9e4b77dd5ed27334bc24a85d0c399e8d0b86de6fb59dadce
-R 89caa52021148a7b8eb691f84233609e
+P bb8f1c16f244f893170f3d03bc445bd15fc337804c7c3e76c548397f5b95b39a
+R 6a60f8ad3d57ac84f5b8c0860a0c4b76
 U drh
-Z e1f8b732b22a9ab7f249168903fe39b6
+Z d1a0a8388ccda2f713b3fe179f34f0f5
 # Remove this line to create a well-formed Fossil manifest.
index 29f502947ffb0fa5de924667b75fce84f228c31a..89e8dac194ac4085a6a421d2b1e79b8626d4df61 100644 (file)
@@ -1 +1 @@
-bb8f1c16f244f893170f3d03bc445bd15fc337804c7c3e76c548397f5b95b39a
\ No newline at end of file
+bc84a82e4ddc1b71025c56c49e62a44f0b12fa87a6417ad61967d9d3121a0d4e
\ No newline at end of file
index 72ec1af10e9452f9f059850ab11a6dbe78cdff2b..6bac63ec518bba680128b1e45cc5b817e0d8787d 100644 (file)
@@ -816,7 +816,7 @@ static void jsonReturn(
             }else if( 0xe2==(u8)c ){
               assert( 0x80==(u8)z[i+1] );
               assert( 0xa8==(u8)z[i+2] || 0xa9==(u8)z[i+2] );
-              i+= 2;
+              i += 2;
               continue;
             }else{
               continue;
@@ -1221,13 +1221,17 @@ json_parse_restart:
            || c=='n' || c=='r' || c=='t'
            || (c=='u' && jsonIs4Hex(&z[j+1])) ){
           jnFlags |= JNODE_ESCAPE;
-        }else if( c=='\'' || c=='0' || c=='v'
-           || c=='\r' || c=='\n'
+        }else if( c=='\'' || c=='0' || c=='v' || c=='\n'
            || (0xe2==(u8)c && 0x80==(u8)z[j+1]
                 && (0xa8==(u8)z[j+2] || 0xa9==(u8)z[j+2]))
            || (c=='x' && jsonIs2Hex(&z[j+1])) ){
           jnFlags |= (JNODE_ESCAPE|JNODE_JSON5);
           pParse->has5 = 1;
+        }else if( c=='\r' ){
+          j++;
+          if( z[j+1]=='\n' ) j++;
+          jnFlags |= (JNODE_ESCAPE|JNODE_JSON5);
+          pParse->has5 = 1;
         }else{
           return -1;
         }
@@ -1270,7 +1274,7 @@ json_parse_restart:
       pParse->has5 = 1;
       jnFlags = JNODE_JSON5;
       seenE = 0;
-      seenDP = 1;
+      seenDP = JSON_REAL;
       goto parse_number_2;
     }
     return -1;
@@ -1335,6 +1339,11 @@ json_parse_restart:
             return i+4;
           }
 #endif
+          if( z[i+1]=='.' ){
+            pParse->has5 = 1;
+            jnFlags |= JNODE_JSON5;
+            goto parse_number_2;
+          }
           return -1;
         }
         if( z[i+1]=='0' ){
@@ -1355,7 +1364,6 @@ json_parse_restart:
       c = z[j];
       if( sqlite3Isdigit(c) ) continue;
       if( c=='.' ){
-        if( z[j-1]=='-' ) return -1;
         if( seenDP==JSON_REAL ) return -1;
         seenDP = JSON_REAL;
         continue;
diff --git a/test/json501.test b/test/json501.test
new file mode 100644 (file)
index 0000000..fbf7bfe
--- /dev/null
@@ -0,0 +1,307 @@
+# 2023-04-27
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements tests for the JSON5 enhancements to the
+# JSON SQL functions extension to the SQLite library.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix json501
+
+# From https://spec.json5.org/#introduction
+#
+#-----------------------------------------------------------------------------
+# Summary of Features
+# 
+# The following ECMAScript 5.1 features, which are not supported in JSON, have
+# been extended to JSON5. 
+#
+# Objects
+#
+#    1) Object keys may be an ECMAScript 5.1 IdentifierName.
+#    2) Objects may have a single trailing comma.
+#
+# Arrays
+#
+#    3) Arrays may have a single trailing comma.
+#
+# Strings
+#
+#    4) Strings may be single quoted.
+#    5) Strings may span multiple lines by escaping new line characters.
+#    6) Strings may include character escapes.
+#
+# Numbers
+#
+#    7) Numbers may be hexadecimal.
+#    8) Numbers may have a leading or trailing decimal point.
+#    9) Numbers may be IEEE 754 positive infinity, negative infinity, and NaN.
+#   10) Numbers may begin with an explicit plus sign.
+#
+# Comments
+#
+#   11) Single and multi-line comments are allowed.
+#
+# White Space
+#
+#   12) Additional white space characters are allowed.
+#-----------------------------------------------------------------------------
+#
+# Test number in this file are of the form X.Y where X is one of the item
+# numbers in the feature list above and Y is the test sequence number.
+#
+
+###############################################################################
+#    1) Object keys may be an ECMAScript 5.1 IdentifierName.
+do_execsql_test 1.1 {
+  WITH c(x) AS (VALUES('{a:5,b:6}'))
+  SELECT x->>'a', json(x), json_valid(x), json_valid5(x) FROM c;
+} {5 {{"a":5,"b":6}} 0 1}
+do_execsql_test 1.2 {
+  SELECT '[7,null,{a:5,b:6},[8,9]]'->>'$[2].b';
+} {6}
+do_execsql_test 1.3 {
+  SELECT '{ $123 : 789 }'->>'$."$123"';
+} 789
+do_execsql_test 1.4 {
+  SELECT '{ _123$xyz : 789 }'->>'$."_123$xyz"';
+} 789
+do_execsql_test 1.5 {
+  SELECT '{ MNO_123$xyz : 789 }'->>'$."MNO_123$xyz"';
+} 789
+
+do_execsql_test 1.6 {
+  SELECT json('{ MNO_123$xyz : 789 }');
+} [list {{"MNO_123$xyz":789}}]
+
+do_catchsql_test 1.10 {
+  SELECT json('{ MNO_123/xyz : 789 }');
+} {1 {malformed JSON}}
+
+# Contra the JSON5 standard, SQLite does not allow non-ASCII characters in
+# an unquoted object label.
+#
+do_catchsql_test 1.11 {
+  SELECT json('{ MNO_123æxyz : 789 }');
+} {1 {malformed JSON}}
+
+###############################################################################
+#    2) Objects may have a single trailing comma.
+
+do_execsql_test 2.1 {
+  WITH c(x) AS (VALUES('{"a":5, "b":6, }'))
+  SELECT x->>'b', json(x), json_valid(x), json_valid5(x) FROM c;
+} {6 {{"a":5,"b":6}} 0 1}
+do_execsql_test 2.2 {
+  SELECT '{a:5, b:6 , }'->>'b';
+} 6
+do_catchsql_test 2.3 {
+  SELECT '{a:5, b:6 ,, }'->>'b';
+} {1 {malformed JSON}}
+do_catchsql_test 2.4 {
+  SELECT '{a:5, b:6, ,}'->>'b';
+} {1 {malformed JSON}}
+
+###############################################################################
+#    3) Arrays may have a single trailing comma.
+
+do_execsql_test 3.1 {
+  WITH c(x) AS (VALUES('[5, 6,]'))
+  SELECT x->>1, json(x), json_valid(x), json_valid5(x) FROM c;
+} {6 {[5,6]} 0 1}
+do_execsql_test 3.2 {
+  SELECT '[5, 6 , ]'->>1;
+} 6
+do_catchsql_test 3.3 {
+  SELECT '[5, 6,,]'->>1;
+} {1 {malformed JSON}}
+do_catchsql_test 3.4 {
+  SELECT '[5, 6 , , ]'->>1;
+} {1 {malformed JSON}}
+
+###############################################################################
+#    4) Strings may be single quoted.
+
+do_execsql_test 4.1 {
+  WITH c(x) AS (VALUES('{"a": ''abcd''}'))
+  SELECT x->>'a', json(x), json_valid(x), json_valid5(x) FROM c;
+} {abcd {{"a":"abcd"}} 0 1}
+do_execsql_test 4.2 {
+  SELECT '{b: 123, ''a'': ''ab\''cd''}'->>'a';
+} {ab'cd}
+
+###############################################################################
+#    5) Strings may span multiple lines by escaping new line characters.
+
+do_execsql_test 5.1 {
+  WITH c(x) AS (VALUES('{a: "abc'||char(0x5c,0x0a)||'xyz"}'))
+  SELECT x->>'a', json(x), json_valid(x), json_valid5(x) FROM c;
+} {abcxyz {{"a":"abcxyz"}} 0 1}
+do_execsql_test 5.2 {
+  SELECT ('{a: "abc'||char(0x5c,0x0d)||'xyz"}')->>'a';
+} {abcxyz}
+do_execsql_test 5.3 {
+  SELECT ('{a: "abc'||char(0x5c,0x0d,0x0a)||'xyz"}')->>'a';
+} {abcxyz}
+do_execsql_test 5.4 {
+  SELECT ('{a: "abc'||char(0x5c,0x2028)||'xyz"}')->>'a';
+} {abcxyz}
+do_execsql_test 5.5 {
+  SELECT ('{a: "abc'||char(0x5c,0x2029)||'xyz"}')->>'a';
+} {abcxyz}
+
+
+###############################################################################
+#    6) Strings may include character escapes.
+
+do_execsql_test 6.1 {
+  SELECT ('{a: "abc'||char(0x5c,0x27)||'xyz"}')->>'a';
+} {abc'xyz}
+do_execsql_test 6.2 {
+  SELECT ('{a: "abc'||char(0x5c,0x22)||'xyz"}')->>'a';
+} {abc"xyz}
+do_execsql_test 6.3 {
+  SELECT ('{a: "abc'||char(0x5c,0x5c)||'xyz"}')->>'a';
+} {{abc\xyz}}
+do_execsql_test 6.4 {
+  SELECT hex(('{a: "abc\bxyz"}')->>'a');
+} {6162630878797A}
+do_execsql_test 6.5 {
+  SELECT hex(('{a: "abc\f\n\r\t\vxyz"}')->>'a');
+} {6162630C0A0D090B78797A}
+do_execsql_test 6.6 {
+  SELECT hex(('{a: "abc\0xyz"}')->>'a');
+} {6162630078797A}
+do_execsql_test 6.7 {
+  SELECT '{a: "abc\x35\x4f\x6Exyz"}'->>'a';
+} {abc5Onxyz}
+do_execsql_test 6.8 {
+  SELECT '{a: "\x6a\x6A\x6b\x6B\x6c\x6C\x6d\x6D\x6e\x6E\x6f\x6F"}'->>'a';
+} {jjkkllmmnnoo}
+
+###############################################################################
+#    7) Numbers may be hexadecimal.
+
+do_execsql_test 7.1 {
+  SELECT '{a: 0x0}'->>'a';
+} 0
+do_execsql_test 7.2 {
+  SELECT '{a: -0x0}'->>'a';
+} 0
+do_execsql_test 7.3 {
+  SELECT '{a: +0x0}'->>'a';
+} 0
+do_execsql_test 7.4 {
+  SELECT '{a: 0xabcdef}'->>'a';
+} 11259375
+do_execsql_test 7.5 {
+  SELECT '{a: -0xaBcDeF}'->>'a';
+} -11259375
+do_execsql_test 7.6 {
+  SELECT '{a: +0xABCDEF}'->>'a';
+} 11259375
+
+###############################################################################
+#    8) Numbers may have a leading or trailing decimal point.
+
+do_execsql_test 8.1 {
+  WITH c(x) AS (VALUES('{x: 4.}')) SELECT x->>'x', json(x) FROM c;
+} {4.0 {{"x":4.0}}}
+do_execsql_test 8.2 {
+  WITH c(x) AS (VALUES('{x: +4.}')) SELECT x->>'x', json(x) FROM c;
+} {4.0 {{"x":4.0}}}
+do_execsql_test 8.3 {
+  WITH c(x) AS (VALUES('{x: -4.}')) SELECT x->>'x', json(x) FROM c;
+} {-4.0 {{"x":-4.0}}}
+do_execsql_test 8.3 {
+  WITH c(x) AS (VALUES('{x: .5}')) SELECT x->>'x', json(x) FROM c;
+} {0.5 {{"x":0.5}}}
+do_execsql_test 8.4 {
+  WITH c(x) AS (VALUES('{x: -.5}')) SELECT x->>'x', json(x) FROM c;
+} {-0.5 {{"x":-0.5}}}
+do_execsql_test 8.5 {
+  WITH c(x) AS (VALUES('{x: +.5}')) SELECT x->>'x', json(x) FROM c;
+} {0.5 {{"x":0.5}}}
+do_execsql_test 8.6 {
+  WITH c(x) AS (VALUES('{x: 4.e0}')) SELECT x->>'x', json(x) FROM c;
+} {4.0 {{"x":4.0e0}}}
+do_execsql_test 8.7 {
+  WITH c(x) AS (VALUES('{x: +4.e1}')) SELECT x->>'x', json(x) FROM c;
+} {40.0 {{"x":4.0e1}}}
+do_execsql_test 8.8 {
+  WITH c(x) AS (VALUES('{x: -4.e2}')) SELECT x->>'x', json(x) FROM c;
+} {-400.0 {{"x":-4.0e2}}}
+do_execsql_test 8.9 {
+  WITH c(x) AS (VALUES('{x: .5e3}')) SELECT x->>'x', json(x) FROM c;
+} {500.0 {{"x":0.5e3}}}
+do_execsql_test 8.10 {
+  WITH c(x) AS (VALUES('{x: -.5e-1}')) SELECT x->>'x', json(x) FROM c;
+} {-0.05 {{"x":-0.5e-1}}}
+do_execsql_test 8.11 {
+  WITH c(x) AS (VALUES('{x: +.5e-2}')) SELECT x->>'x', json(x) FROM c;
+} {0.005 {{"x":0.5e-2}}}
+
+
+###############################################################################
+#    9) Numbers may be IEEE 754 positive infinity, negative infinity, and NaN.
+
+do_execsql_test 9.1 {
+  WITH c(x) AS (VALUES('{x: +Infinity}')) SELECT x->>'x', json(x) FROM c;
+} {Inf {{"x":9.0e999}}}
+do_execsql_test 9.2 {
+  WITH c(x) AS (VALUES('{x: -Infinity}')) SELECT x->>'x', json(x) FROM c;
+} {-Inf {{"x":-9.0e999}}}
+do_execsql_test 9.3 {
+  WITH c(x) AS (VALUES('{x: Infinity}')) SELECT x->>'x', json(x) FROM c;
+} {Inf {{"x":9.0e999}}}
+do_execsql_test 9.4 {
+  WITH c(x) AS (VALUES('{x: NaN}')) SELECT x->>'x', json(x) FROM c;
+} {{} {{"x":null}}}
+
+###############################################################################
+#   10) Numbers may begin with an explicit plus sign.
+
+do_execsql_test 10.1 {
+  SELECT '{a: +123}'->'a';
+} 123
+
+###############################################################################
+#   11) Single and multi-line comments are allowed.
+
+do_execsql_test 11.1 {
+  SELECT ' /* abc */ { /*def*/ aaa /* xyz */ : // to the end of line
+          123 /* xyz */ , /* 123 */ }'->>'aaa';
+} 123
+
+###############################################################################
+#   12) Additional white space characters are allowed.
+
+do_execsql_test 12.1 {
+  SELECT (char(0x09,0x0a,0x0b,0x0c,0x0d,0x20,0xa0,0x2028,0x2029)
+          || '{a: "xyz"}')->>'a';
+} xyz
+do_execsql_test 12.2 {
+  SELECT ('{a:' || char(0x09,0x0a,0x0b,0x0c,0x0d,0x20,0xa0,0x2028,0x2029)
+          || '"xyz"}')->>'a';
+} xyz
+do_execsql_test 12.3 {
+  SELECT (char(0x1680,0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,
+               0x2006,0x2007,0x2008,0x2009,0x200a,0x3000,0xfeff)
+          || '{a: "xyz"}')->>'a';
+} xyz
+do_execsql_test 12.4 {
+  SELECT ('{a: ' ||char(0x1680,0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,
+                        0x2006,0x2007,0x2008,0x2009,0x200a,0x3000,0xfeff)
+          || ' "xyz"}')->>'a';
+} xyz
+
+
+finish_test