mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add support for JSON5.
FossilOrigin-Name: f8c3ed23a6931b1da3b93b3274b132387078112a5c8e8d06b5312c47987d3937
This commit is contained in:
27
test/json/README.md
Normal file
27
test/json/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
The files in this subdirectory are used to help measure the performance
|
||||
of the SQLite JSON parser.
|
||||
|
||||
# 1.0 Prerequisites
|
||||
|
||||
1. Valgrind
|
||||
|
||||
2. Fossil
|
||||
|
||||
# 2.0 Setup
|
||||
|
||||
1. Run: "`tclsh json-generator.tcl | sqlite3 json100mb.db`" to create
|
||||
the 100 megabyte test database. Do this so that the "json100mb.db"
|
||||
file lands in the directory from which you will run tests, not in
|
||||
the test/json subdirectory of the source tree.
|
||||
|
||||
2. Build the baseline sqlite3.c file. ("`make sqlite3.c`")
|
||||
|
||||
3. Run "`sh json-speed-check-1.sh trunk`". This creates the baseline
|
||||
profile in "jout-trunk.txt".
|
||||
|
||||
# 3.0 Testing
|
||||
|
||||
1. Build the sqlite3.c to be tested.
|
||||
|
||||
2. Run "`sh json-speed-check-1.sh x1`". The profile output will appear
|
||||
in jout-x1.txt. Substitute any label you want in place of "x1".
|
401
test/json/json-generator.tcl
Normal file
401
test/json/json-generator.tcl
Normal file
@ -0,0 +1,401 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# Generate SQL that will populate an SQLite database with about 100 megabytes
|
||||
# of pseudo-random JSON text.
|
||||
#
|
||||
# tclsh json-generator.tcl | sqlite3 json110mb.db
|
||||
#
|
||||
# srand() is used to initialize the random seed so that the same JSON
|
||||
# is generated for every run.
|
||||
#
|
||||
expr srand(12345678)
|
||||
set wordlist {
|
||||
ability able abroad access account act
|
||||
action active actor add address adept
|
||||
adroit advance advice affect age ageless
|
||||
agency agent agile agree air airfare
|
||||
airline airport alert almond alpha always
|
||||
amend amount amplify analyst anchor angel
|
||||
angelic angle ankle annual answer antique
|
||||
anybody anyhow appeal apple apricot apt
|
||||
area argon arm army arrival arsenic
|
||||
art artful article arugula aside ask
|
||||
aspect assist assume atom atone attempt
|
||||
author autumn average avocado award awl
|
||||
azure back bacon bag bagel bake
|
||||
baker balance ball balloon bamboo banana
|
||||
band banjo bank barium base basil
|
||||
basin basis basket bass bat bath
|
||||
battery beach beak bean bear bearcub
|
||||
beauty beef beet beige being bell
|
||||
belly belt bench bend benefit best
|
||||
beta better beyond bicycle bid big
|
||||
bike bill bird biscuit bismuth bisque
|
||||
bit black blank blest blind bliss
|
||||
block bloom blue board boat body
|
||||
bokchoy bone bonus book bookish boot
|
||||
border boron boss bossy bottle bottom
|
||||
bow bowl bowtie box brain brainy
|
||||
branch brave bravely bread break breath
|
||||
breezy brick bridge brie brief briefly
|
||||
bright broad broil bromine bronze brother
|
||||
brow brown brush buddy budget buffalo
|
||||
bug bugle bull bunch burger burly
|
||||
burrito bus busy butter button buy
|
||||
buyer byte cab cabbage cabinet cable
|
||||
cadet cadmium caesium cake calcium caliper
|
||||
call caller calm calmly camera camp
|
||||
can canary cancel candle candy cap
|
||||
capable caper capital captain car carbon
|
||||
card care career careful carp carpet
|
||||
carrot carry case cash cassava casual
|
||||
cat catch catfish catsear catsup cause
|
||||
cave celery cell century chain chair
|
||||
chalk chance change channel chapter chard
|
||||
charge charity chart check cheddar cheery
|
||||
cheese chicken chicory chiffon child chin
|
||||
chip chives choice chowder chum church
|
||||
circle city claim clam class classic
|
||||
classy clay clean cleaner clear clearly
|
||||
clerk click client climate clock clorine
|
||||
closet clothes cloud clown club clue
|
||||
cluster coach coast coat cobbler cobolt
|
||||
cod code coffee colby cold collar
|
||||
college comb combine comet comfort command
|
||||
comment common company complex concept concern
|
||||
concert conduit consist contact contest context
|
||||
control convert cook cookie copilot copper
|
||||
copy coral cordial corn corner corny
|
||||
correct cost count counter country county
|
||||
couple courage course court cover cow
|
||||
cowbird crab crack craft crash crazy
|
||||
cream credit creek cress crevice crew
|
||||
crimson croaker crop cross crowd cube
|
||||
cuckoo cuisine culture cup current curve
|
||||
cut cyan cycle dagger daily dance
|
||||
dare darter data date day daylily
|
||||
deal dear dearly debate debit decade
|
||||
decimal deep deft deftly degree delay
|
||||
deluxe deposit depth design desk detail
|
||||
device dew diamond diet dig dill
|
||||
dinner dip direct dirt dish disk
|
||||
display diver divide divine doctor dodger
|
||||
donut door dot double dough draft
|
||||
drag dragon drama draw drawer drawing
|
||||
dream drill drink drive driver drop
|
||||
drum dry dryer drywall duck due
|
||||
dump dusk dust duty dye eagle
|
||||
ear earring earth ease east easy
|
||||
eat economy edge editor eel effect
|
||||
effort egg eight elbow elegant element
|
||||
elf elk email emerald employ end
|
||||
endive endless energy engine enjoy enter
|
||||
entry equal equip error escape essay
|
||||
eternal evening event exam example excuse
|
||||
exit expert extent extreme eye face
|
||||
fact factor factual fail failure fair
|
||||
fajita fall family fan fang farm
|
||||
farmer fat fault feature feed feel
|
||||
feeling fench fennel festive few fiber
|
||||
field fig figure file fill film
|
||||
filter final finance finding finger finish
|
||||
fire fish fishing fit fitting five
|
||||
fix flier flight floor floral florine
|
||||
flour flow flower fly flying focus
|
||||
fold folding food foot force forest
|
||||
forever forgive form formal format fortune
|
||||
forum frame free freedom freely fresh
|
||||
friend frog front fruit fuchsia fuel
|
||||
fun funny future gain galaxy gallium
|
||||
game gamma gap garage garden garlic
|
||||
gas gate gather gauge gear gem
|
||||
gene general gentle gently gherkin ghost
|
||||
gift give glad glass gleeful glossy
|
||||
glove glue goal goat goby gold
|
||||
goldeye golf good gouda goulash gourd
|
||||
grab grace grade gram grand grape
|
||||
grapes grass gravy gray great green
|
||||
grits grocery ground group grouper grout
|
||||
growth guard guave guess guest guide
|
||||
guitar gumbo guppy habit hacksaw haddock
|
||||
hafnium hagfish hair half halibut hall
|
||||
hammer hand handle handy hanger happy
|
||||
hat havarti hay haybale head health
|
||||
healthy hearing heart hearty heat heavy
|
||||
heel height helium hello help helpful
|
||||
herald herring hide high highly highway
|
||||
hill hip hipster hire history hit
|
||||
hoki hold hole holiday holly home
|
||||
honest honey hook hope hopeful horizon
|
||||
horn horse host hotel hour house
|
||||
housing human humane humor hunt hurry
|
||||
ice icecube icefish icy idea ideal
|
||||
image impact impress inch income indigo
|
||||
initial inkpen insect inside intense invite
|
||||
iodine iridium iron island issue item
|
||||
ivory jacket jargon javelin jello jelly
|
||||
jewel job jocund join joint joke
|
||||
jovial joy joyful joyous judge juice
|
||||
jump junior jury just justice kale
|
||||
keel keep kelp ketchup key keyhole
|
||||
keyway khaki kick kid kidney kiloohm
|
||||
kind kindly king kitchen kite kiwi
|
||||
knee knife krill krypton kumquat lab
|
||||
lace lack ladder lake lamp lamprey
|
||||
land laser laugh law lawn lawyer
|
||||
layer lead leader leading leaf leafy
|
||||
league leather leave lecture leek leg
|
||||
lemon length lentil lesson let letter
|
||||
lettuce level library life lift light
|
||||
lily lime limit line linen link
|
||||
lip list listen lithium lively living
|
||||
lizard load loan lobster local lock
|
||||
log long longfin look lotus love
|
||||
lovely loving low lucid luck luffa
|
||||
lunch lung machine magenta magnet mail
|
||||
main major make mall manager mango
|
||||
manner many map march market maroon
|
||||
martian master match math matter maximum
|
||||
maybe meal meaning meat media medium
|
||||
meet meeting melody melon member memory
|
||||
mention menu mercury merry mess message
|
||||
messy metal meter method micron middle
|
||||
might mile milk mind mine minimum
|
||||
minnow minor mint minute mirror miss
|
||||
mission misty mix mixer mixture mobile
|
||||
mode model moment monitor monk month
|
||||
moon moray morning most motor mouse
|
||||
mouth move mover movie much mud
|
||||
mudfish muffin mullet munster muon muscle
|
||||
music mustard nail name nation native
|
||||
natural nature navy neat neatly nebula
|
||||
neck needle neon nerve net network
|
||||
neutron news nibble nice nickel night
|
||||
niobium nobody noise noodle normal north
|
||||
nose note nothing notice nova novel
|
||||
number nurse nursery oar object offer
|
||||
office officer oil okay okra old
|
||||
olive one onion open opening opinion
|
||||
option orange orbit orchid order oregano
|
||||
other ounce outcome outside oven owner
|
||||
oxygen oyster pace pack package page
|
||||
pager paint pair pale pan pancake
|
||||
papaya paper pardon parent park parking
|
||||
parsley parsnip part partner party pass
|
||||
passage past pasta path patient pattern
|
||||
pause pay pea peace peach peacock
|
||||
peahen peak peanut pear pearl pen
|
||||
penalty pencil pension people pepper perch
|
||||
perfect period permit person phase phone
|
||||
photo phrase physics piano pick picture
|
||||
pie piece pigeon pike pilot pin
|
||||
pink pinkie pious pipe pitch pizza
|
||||
place plan plane planet plant planter
|
||||
plastic plate play player playful plenty
|
||||
pliers plum pod poem poet poetry
|
||||
point police policy pollock pony pool
|
||||
pop popover poptart pork port portal
|
||||
post pot potato pound powder power
|
||||
present press price pride primary print
|
||||
prior private prize problem process produce
|
||||
product profile profit program project promise
|
||||
prompt proof proper protein proton public
|
||||
puff puffer pull pumpkin pup pupfish
|
||||
pure purple purpose push put quality
|
||||
quark quarter quiet quill quit quote
|
||||
rabbit raccoon race radiant radio radish
|
||||
radium radon rain rainbow raise ramp
|
||||
ranch range rasp rate ratio ray
|
||||
razor reach read reading real reality
|
||||
reason recipe record recover red redeem
|
||||
reed reef refuse region regret regular
|
||||
relaxed release relief relish remote remove
|
||||
rent repair repeat reply report request
|
||||
reserve resist resolve resort rest result
|
||||
return reveal review reward ribbon rice
|
||||
rich ride ridge right ring rise
|
||||
risk river rivet road roast rock
|
||||
rocket role roll roof room rope
|
||||
rose rough roughy round row royal
|
||||
rub ruby rudder ruin rule run
|
||||
runner rush rust sacred saddle safe
|
||||
safety sail salad salami sale salmon
|
||||
salt sample sand sander sandy sauce
|
||||
save saving saw scale scampi scene
|
||||
scheme school score screen script sea
|
||||
search season seat second secret sector
|
||||
seemly self sell senate senior sense
|
||||
series serve set shake shape share
|
||||
shark shell shift shine shiny ship
|
||||
shock shoe shoot shop shovel show
|
||||
side sign signal silk silly silver
|
||||
simple sing singer single sink site
|
||||
size skill skin sky slate sleep
|
||||
sleepy slice slide slip smart smell
|
||||
smelt smile smoke smooth snap snipe
|
||||
snow snowy sock socket sodium soft
|
||||
softly soil sole solid song sorrel
|
||||
sort soul sound soup source south
|
||||
space spare speech speed spell spend
|
||||
sphere spice spider spirit spite split
|
||||
spoon sport spot spray spread spring
|
||||
squab square squash stable staff stage
|
||||
stand staple star start state status
|
||||
stay steak steel step stern stew
|
||||
stick still stock stone stop store
|
||||
storm story strain street stress strike
|
||||
string stroke strong studio study stuff
|
||||
style sugar suit sulfur summer sun
|
||||
sunny sunset super superb surf survey
|
||||
sweet swim swing switch symbol system
|
||||
table tackle tail tale talk tan
|
||||
tank tap tape target task taste
|
||||
tau tea teach teal team tear
|
||||
tell ten tender tennis tent term
|
||||
test tetra text thanks theme theory
|
||||
thing think thread throat thumb ticket
|
||||
tidy tie tiger till time timely
|
||||
tin tip title toast today toe
|
||||
tomato tone tongue tool tooth top
|
||||
topic total touch tough tour towel
|
||||
tower town track trade train trash
|
||||
travel tray treat tree trick trip
|
||||
trout trowel truck trupet trust truth
|
||||
try tube tuna tune turf turkey
|
||||
turn turnip tutor tux tweet twist
|
||||
two type union unique unit upbeat
|
||||
upper use useful user usual valley
|
||||
value van vase vast veil vein
|
||||
velvet verse very vessel vest video
|
||||
view violet visit visual vivid voice
|
||||
volume vowel voyage waffle wait wake
|
||||
walk wall warm warmth wasabi wash
|
||||
watch water wave wax way wealth
|
||||
wear web wedge week weekly weight
|
||||
west whale what wheat wheel when
|
||||
where while who whole why will
|
||||
win wind window wing winner winter
|
||||
wire wish witty wolf wonder wood
|
||||
wool woolly word work worker world
|
||||
worry worth worthy wrap wrench wrist
|
||||
writer xenon yak yam yard yarrow
|
||||
year yearly yellow yew yogurt young
|
||||
youth zebra zephyr zinc zone zoo
|
||||
}
|
||||
set nwordlist [llength $wordlist]
|
||||
|
||||
proc random_char {} {
|
||||
return [string index \
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
|
||||
[expr {int(rand()*52)}]]
|
||||
}
|
||||
proc random_label {} {
|
||||
set label [random_char]
|
||||
while {rand()>0.8} {
|
||||
append label [random_char]
|
||||
}
|
||||
if {rand()>0.9} {append label -}
|
||||
append label [format %d [expr {int(rand()*100)}]]
|
||||
return $label
|
||||
}
|
||||
proc random_numeric {} {
|
||||
set n [expr {(rand()*2-1.0)*1e6}]
|
||||
switch [expr {int(rand()*6)}] {
|
||||
0 {set format %.3f}
|
||||
1 {set format %.6E}
|
||||
2 {set format %.4e}
|
||||
default {set format %g}
|
||||
}
|
||||
return [format $format $n]
|
||||
}
|
||||
|
||||
|
||||
proc random_json {limit indent} {
|
||||
global nwordlist wordlist
|
||||
set res {}
|
||||
if {$indent==0 || ($limit>0 && rand()>0.5)} {
|
||||
incr limit -1
|
||||
incr indent 2
|
||||
set n [expr {int(rand()*5)+1}]
|
||||
if {$n==5} {incr n [expr {int(rand()*10)}]}
|
||||
if {rand()>0.5} {
|
||||
set res \173\n
|
||||
for {set i 0} {$i<$n} {incr i} {
|
||||
append res [string repeat { } $indent]
|
||||
if {rand()>0.8} {
|
||||
if {rand()>0.5} {
|
||||
set sep ":\n [string repeat { } $indent]"
|
||||
} else {
|
||||
set sep " : "
|
||||
}
|
||||
} else {
|
||||
set sep :
|
||||
}
|
||||
append res \"[random_label]\"$sep[random_json $limit $indent]
|
||||
if {$i<$n-1} {append res ,}
|
||||
append res \n
|
||||
}
|
||||
incr indent -2
|
||||
append res [string repeat { } $indent]
|
||||
append res \175
|
||||
return $res
|
||||
} else {
|
||||
set res \[\n
|
||||
for {set i 0} {$i<$n} {incr i} {
|
||||
append res [string repeat { } $indent]
|
||||
append res [random_json $limit $indent]
|
||||
if {$i<$n-1} {append res ,}
|
||||
append res \n
|
||||
}
|
||||
incr indent -2
|
||||
append res [string repeat { } $indent]
|
||||
append res \]
|
||||
return $res
|
||||
}
|
||||
} elseif {rand()>0.9} {
|
||||
if {rand()>0.7} {return "true"}
|
||||
if {rand()>0.5} {return "false"}
|
||||
return "null"
|
||||
} elseif {rand()>0.5} {
|
||||
return [random_numeric]
|
||||
} else {
|
||||
set res \"
|
||||
set n [expr {int(rand()*4)+1}]
|
||||
if {$n>=4} {set n [expr {$n+int(rand()*6)}]}
|
||||
for {set i 0} {$i<$n} {incr i} {
|
||||
if {rand()<0.05} {
|
||||
set w [random_numeric]
|
||||
} else {
|
||||
set k [expr {int(rand()*$nwordlist)}]
|
||||
set w [lindex $wordlist $k]
|
||||
}
|
||||
if {rand()<0.07} {
|
||||
set w \\\"$w\\\"
|
||||
}
|
||||
if {$i<$n-1} {
|
||||
switch [expr {int(rand()*9)}] {
|
||||
0 {set sp {, }}
|
||||
1 {set sp "\\n "}
|
||||
2 {set sp "-"}
|
||||
default {set sp { }}
|
||||
}
|
||||
append res $w$sp
|
||||
} else {
|
||||
append res $w
|
||||
if {rand()<0.2} {append res .}
|
||||
}
|
||||
}
|
||||
return $res\"
|
||||
}
|
||||
}
|
||||
|
||||
puts "CREATE TABLE IF NOT EXISTS data1(x JSON);"
|
||||
puts "BEGIN;"
|
||||
set sz 0
|
||||
for {set i 0} {$sz<100000000} {incr i} {
|
||||
set j [random_json 7 0]
|
||||
incr sz [string length $j]
|
||||
puts "INSERT INTO data1(x) VALUES('$j');"
|
||||
}
|
||||
puts "COMMIT;"
|
||||
puts "SELECT sum(length(x)) FROM data1;"
|
4
test/json/json-q1.txt
Normal file
4
test/json/json-q1.txt
Normal file
@ -0,0 +1,4 @@
|
||||
.mode qbox
|
||||
.timer on
|
||||
.param set $label 'q87'
|
||||
SELECT rowid, x->>$label FROM data1 WHERE x->>$label IS NOT NULL;
|
80
test/json/json-speed-check.sh
Executable file
80
test/json/json-speed-check.sh
Executable file
@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This is a template for a script used for day-to-day size and
|
||||
# performance monitoring of SQLite. Typical usage:
|
||||
#
|
||||
# sh speed-check.sh trunk # Baseline measurement of trunk
|
||||
# sh speed-check.sh x1 # Measure some experimental change
|
||||
# fossil xdiff --tk jout-trunk.txt jout-x1.txt # View chanages
|
||||
#
|
||||
# There are multiple output files, all with a base name given by
|
||||
# the first argument:
|
||||
#
|
||||
# summary-$BASE.txt # Copy of standard output
|
||||
# jout-$BASE.txt # cachegrind output
|
||||
# explain-$BASE.txt # EXPLAIN listings (only with --explain)
|
||||
#
|
||||
if test "$1" = ""
|
||||
then
|
||||
echo "Usage: $0 OUTPUTFILE [OPTIONS]"
|
||||
exit
|
||||
fi
|
||||
NAME=$1
|
||||
shift
|
||||
#CC_OPTS="-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MEMSYS5"
|
||||
CC_OPTS="-DSQLITE_ENABLE_MEMSYS5"
|
||||
CC=gcc
|
||||
LEAN_OPTS="-DSQLITE_THREADSAFE=0"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_MEMSTATUS=0"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_LIKE_DOESNT_MATCH_BLOBS"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_MAX_EXPR_DEPTH=0"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DECLTYPE"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DEPRECATED"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_PROGRESS_CALLBACK"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_SHARED_CACHE"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_USE_ALLOCA"
|
||||
BASELINE="trunk"
|
||||
doExplain=0
|
||||
doCachegrind=1
|
||||
doVdbeProfile=0
|
||||
doWal=1
|
||||
doDiff=1
|
||||
while test "$1" != ""; do
|
||||
case $1 in
|
||||
--nodiff)
|
||||
doDiff=0
|
||||
;;
|
||||
--lean)
|
||||
CC_OPTS="$CC_OPTS $LEAN_OPTS"
|
||||
;;
|
||||
--clang)
|
||||
CC=clang
|
||||
;;
|
||||
--gcc7)
|
||||
CC=gcc-7
|
||||
;;
|
||||
-*)
|
||||
CC_OPTS="$CC_OPTS $1"
|
||||
;;
|
||||
*)
|
||||
BASELINE=$1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
echo "NAME = $NAME" | tee summary-$NAME.txt
|
||||
echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt
|
||||
rm -f cachegrind.out.* jsonshell
|
||||
$CC -g -Os -Wall -I. $CC_OPTS ./shell.c ./sqlite3.c -o jsonshell -ldl -lpthread
|
||||
ls -l jsonshell | tee -a summary-$NAME.txt
|
||||
home=`echo $0 | sed -e 's,/[^/]*$,,'`
|
||||
echo ./jsonshell json100mb.db "<$home/json-q1.txt"
|
||||
valgrind --tool=cachegrind ./jsonshell json100mb.db <$home/json-q1.txt \
|
||||
2>&1 | tee -a summary-$NAME.txt
|
||||
cg_anno.tcl cachegrind.out.* >jout-$NAME.txt
|
||||
echo '*****************************************************' >>jout-$NAME.txt
|
||||
sed 's/^[0-9=-]\{9\}/==00000==/' summary-$NAME.txt >>jout-$NAME.txt
|
||||
if test "$NAME" != "$BASELINE"; then
|
||||
fossil xdiff --tk -c 20 jout-$BASELINE.txt jout-$NAME.txt
|
||||
fi
|
@ -310,12 +310,33 @@ do_execsql_test json-6.1 {
|
||||
SELECT json_valid('{"a":55,"b":72,}');
|
||||
} {0}
|
||||
do_execsql_test json-6.2 {
|
||||
SELECT json_error_position('{"a":55,"b":72,}');
|
||||
} {0}
|
||||
do_execsql_test json-6.3 {
|
||||
SELECT json_valid(json('{"a":55,"b":72,}'));
|
||||
} {1}
|
||||
do_execsql_test json-6.4 {
|
||||
SELECT json_valid('{"a":55,"b":72 , }');
|
||||
} {0}
|
||||
do_execsql_test json-6.5 {
|
||||
SELECT json_error_position('{"a":55,"b":72 , }');
|
||||
} {0}
|
||||
do_execsql_test json-6.6 {
|
||||
SELECT json_error_position('{"a":55,"b":72,,}');
|
||||
} {16}
|
||||
do_execsql_test json-6.7 {
|
||||
SELECT json_valid('{"a":55,"b":72}');
|
||||
} {1}
|
||||
do_execsql_test json-6.3 {
|
||||
SELECT json_valid('["a",55,"b",72,]');
|
||||
do_execsql_test json-6.8 {
|
||||
SELECT json_error_position('["a",55,"b",72,]');
|
||||
} {0}
|
||||
do_execsql_test json-6.4 {
|
||||
do_execsql_test json-6.9 {
|
||||
SELECT json_error_position('["a",55,"b",72 , ]');
|
||||
} {0}
|
||||
do_execsql_test json-6.10 {
|
||||
SELECT json_error_position('["a",55,"b",72,,]');
|
||||
} {16}
|
||||
do_execsql_test json-6.11 {
|
||||
SELECT json_valid('["a",55,"b",72]');
|
||||
} {1}
|
||||
|
||||
|
@ -301,18 +301,27 @@ for {set i 0} {$i<100} {incr i} {
|
||||
# allowing them. The following tests verify that the problem is now
|
||||
# fixed.
|
||||
#
|
||||
do_execsql_test json102-1401 { SELECT json_valid('{"x":01}') } 0
|
||||
do_execsql_test json102-1402 { SELECT json_valid('{"x":-01}') } 0
|
||||
do_execsql_test json102-1403 { SELECT json_valid('{"x":0}') } 1
|
||||
do_execsql_test json102-1404 { SELECT json_valid('{"x":-0}') } 1
|
||||
do_execsql_test json102-1405 { SELECT json_valid('{"x":0.1}') } 1
|
||||
do_execsql_test json102-1406 { SELECT json_valid('{"x":-0.1}') } 1
|
||||
do_execsql_test json102-1407 { SELECT json_valid('{"x":0.0000}') } 1
|
||||
do_execsql_test json102-1408 { SELECT json_valid('{"x":-0.0000}') } 1
|
||||
do_execsql_test json102-1409 { SELECT json_valid('{"x":01.5}') } 0
|
||||
do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0
|
||||
do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0
|
||||
do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0
|
||||
foreach {id j x0 x5} {
|
||||
1401 {'{"x":01}'} 0 0
|
||||
1402 {'{"x":-01}'} 0 0
|
||||
1403 {'{"x":0}'} 1 1
|
||||
1404 {'{"x":-0}'} 1 1
|
||||
1405 {'{"x":0.1}'} 1 1
|
||||
1406 {'{"x":-0.1}'} 1 1
|
||||
1407 {'{"x":0.0000}'} 1 1
|
||||
1408 {'{"x":-0.0000}'} 1 1
|
||||
1409 {'{"x":01.5}'} 0 0
|
||||
1410 {'{"x":-01.5}'} 0 0
|
||||
1411 {'{"x":00}'} 0 0
|
||||
1412 {'{"x":-00}'} 0 0
|
||||
1413 {'{"x":+0}'} 0 1
|
||||
1414 {'{"x":+5}'} 0 1
|
||||
1415 {'{"x":+5.5}'} 0 1
|
||||
} {
|
||||
do_execsql_test json102-$id "
|
||||
SELECT json_valid($j), NOT json_error_position($j);
|
||||
" [list $x0 $x5]
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
# 2017-04-10 ticket 6c9b5514077fed34551f98e64c09a10dc2fc8e16
|
||||
|
@ -30,6 +30,48 @@ do_execsql_test json104-100 {
|
||||
}
|
||||
}');
|
||||
} {{{"a":"z","c":{"d":"e"}}}}
|
||||
do_execsql_test json104-101 {
|
||||
SELECT json_patch('{
|
||||
"a": "b",
|
||||
"c": {
|
||||
"d": "e",
|
||||
"f": "g"
|
||||
}
|
||||
}','{
|
||||
a:"z",
|
||||
c: {
|
||||
f: null
|
||||
}
|
||||
}');
|
||||
} {{{"a":"z","c":{"d":"e"}}}}
|
||||
do_execsql_test json104-102 {
|
||||
SELECT json_patch('{
|
||||
a: "b",
|
||||
c: {
|
||||
d: "e",
|
||||
f: "g"
|
||||
}
|
||||
}','{
|
||||
"a":"z",
|
||||
"c": {
|
||||
"f": null
|
||||
}
|
||||
}');
|
||||
} {{{"a":"z","c":{"d":"e"}}}}
|
||||
do_execsql_test json104-103 {
|
||||
SELECT json_patch('{
|
||||
a: "b",
|
||||
c: {
|
||||
d: "e",
|
||||
f: "g"
|
||||
}
|
||||
}','{
|
||||
a:"z",
|
||||
c: {
|
||||
f: null
|
||||
}
|
||||
}');
|
||||
} {{{"a":"z","c":{"d":"e"}}}}
|
||||
|
||||
|
||||
# This is the example from pages 4 and 5 of RFC-7396
|
||||
|
304
test/json501.test
Normal file
304
test/json501.test
Normal file
@ -0,0 +1,304 @@
|
||||
# 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), NOT json_error_position(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}}
|
||||
|
||||
do_execsql_test 1.11 {
|
||||
SELECT '{ MNO_123æxyz : 789 }'->>'MNO_123æxyz';
|
||||
} {789}
|
||||
|
||||
###############################################################################
|
||||
# 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), NOT json_error_position(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), NOT json_error_position(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), NOT json_error_position(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), NOT json_error_position(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
|
25
test/json502.test
Normal file
25
test/json502.test
Normal file
@ -0,0 +1,25 @@
|
||||
# 2023-04-28
|
||||
#
|
||||
# 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 json502
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(x JSON);
|
||||
INSERT INTO t1(x) VALUES('{a:{b:{c:"hello",},},}');
|
||||
SELECT fullkey FROM t1, json_tree(x);
|
||||
} {{$} {$.a} {$.a.b} {$.a.b.c}}
|
||||
|
||||
finish_test
|
Reference in New Issue
Block a user