diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 2cbcbff89e..67a0ea2096 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -644,6 +644,9 @@ static void fts3DatabasePageSize(int *pRc, Fts3Table *p){ sqlite3_step(pStmt); p->nPgsz = sqlite3_column_int(pStmt, 0); rc = sqlite3_finalize(pStmt); + }else if( rc==SQLITE_AUTH ){ + p->nPgsz = 1024; + rc = SQLITE_OK; } } assert( p->nPgsz>0 || rc!=SQLITE_OK ); diff --git a/manifest b/manifest index 9fde5b8fdf..c5e575d44c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\ssessions\sbranch\swith\slatest\strunk\schanges. -D 2011-06-22T12:01:09 +C Pull\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch. +D 2011-06-23T02:11:11.003 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -62,7 +62,7 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 1c8a45dfd6836e7dea0307008079793ac0fc3b68 +F ext/fts3/fts3.c ca776037493d0081da70a6afc0df80f5ce347cb7 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h fa493ccbad78a2c99ad1c984f651c0c202e68536 F ext/fts3/fts3_aux.c 0ebfa7b86cf8ff6a0861605fcc63b83ec1b70691 @@ -198,7 +198,7 @@ F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c 6a34149c9ff4a6f998a4cb8336d4481670b576b6 -F src/test1.c ce2fab9e36932f5771c35291539366c9af229df3 +F src/test1.c 669b8fde7f3c72250d59fef1adda5e040f7baae0 F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432 F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7 @@ -238,7 +238,7 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd F src/test_syscall.c 162c4ec0137a549c009bb9ecab550527743cfc5d F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa F src/test_thread.c fe9a7803fc1d69cccb60f016f28c1cedf2d9fcfa -F src/test_vfs.c 1d82aee93e644188179da2165f4fe3ad6b62782c +F src/test_vfs.c 956cb3f5cbd2a0d09129540e615bb0fb761c083d F src/test_vfstrace.c 0b884e06094a746da729119a2cabdc7aa790063d F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 @@ -251,7 +251,7 @@ F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e F src/vdbe.c df52db6162fd94767b76bb4e9a7cb9207e83086f F src/vdbe.h 322af148cceef120bb1ec9cff7f122e76abf94da F src/vdbeInt.h 3de6588b36c833969aebab202e1766d586c37ec2 -F src/vdbeapi.c 3f6e988bd19391be1aa49ffd1f259654dcc8d975 +F src/vdbeapi.c 1d947da083c24e8bf61823f02f619a1f4a682100 F src/vdbeaux.c db3d4eedccea5add714dfb8b10f70d0f8d692db5 F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b @@ -492,7 +492,7 @@ F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3shared.test 8bb266521d7c5495c0ae522bb4d376ad5387d4a2 F test/fts3snippet.test a12f22a3ba4dd59751a57c79b031d07ab5f51ddd F test/fts3sort.test 63d52c1812904b751f9e1ff487472e44833f5402 -F test/fts4aa.test b99ad4d9a43a00efd096ef4d0b082de58d848d41 +F test/fts4aa.test 148d9eb54901af23b5d402b1f388f43e559e1728 F test/func.test 6c5ce11e3a0021ca3c0649234e2d4454c89110ca F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 7ba2ca5a1e9bca900ba2c230cf04bd67184bc1bc @@ -614,7 +614,7 @@ F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec -F test/oserror.test 498d8337e9d15543eb7b004fef8594bf204ff43c +F test/oserror.test 3fe52e0bd2891a9bf7cdeb639554992453d46301 F test/pager1.test 228a831060dab96bc91b03ba2a85cedefd1ab38a F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f @@ -849,7 +849,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4 F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31 F test/triggerA.test eaf11a29db2a11967d2d4b49d37f92bce598194e F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe -F test/triggerC.test 811ab569af9e6fc894afbcc0d77d14500b2406c5 +F test/triggerC.test 02c690febf608ae20b9af86184a9867f79855b1d F test/triggerD.test c6add3817351451e419f6ff9e9a259b02b6e2de7 F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff @@ -889,7 +889,7 @@ F test/wal.test 5617ad308bfdb8a8885220d8a261a6096a8d7e57 F test/wal2.test aa0fb2314b3235be4503c06873e41ebfc0757782 F test/wal3.test 5c396cc22497244d627306f4c1d360167353f8dd F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30 -F test/wal5.test 1bbfaa316dc2a1d0d1fac3f4500c38a90055a41b +F test/wal5.test f06a0427e06db00347e32eb9fa99d6a5c0f2d088 F test/wal6.test 07aa31ca8892d0527f2c5c5a9a2a87aa421dfaa8 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe @@ -934,7 +934,7 @@ F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c.tcl 1fa0ed9cfdc768bf5de7e65fda8d97a46dd2a7e6 F tool/mksqlite3h.tcl 78013ad79a5e492e5f764f3c7a8ef834255061f8 F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87 -F tool/omittest.tcl b1dd290c1596e0f31fd335160a74ec5dfea3df4a +F tool/omittest.tcl 8086c014cbae90f1f2b564d59d05a5e4ac1783c9 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5 @@ -959,7 +959,7 @@ F tool/symbols.sh bc2a3709940d47c8ac8e0a1fdf17ec801f015a00 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 347d974d143cf132f953b565fbc03026f19fcb4d -P f3d148e0d10e16cd744ec88a2961fd617368c5ed 6e1f4df51ad32e36715cba16f9df0d17a08dc653 -R 13b557f9f4fbb1acb5f4e9d6383e3c30 -U dan -Z e013d0e7eccb6ac9a42c9313b4aac9ad +P 48d5cab3ac08b25ec94d6ecfd25779320558110f 8dca748b23fa6f9abf47a186dcd1766f4dcf3ab7 +R 3169acda05ed5fbe4acf037bcfc9a4ff +U drh +Z 2442f47412d7510881ef0ca2870675d8 diff --git a/manifest.uuid b/manifest.uuid index 86f3655672..63b5313abf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -48d5cab3ac08b25ec94d6ecfd25779320558110f \ No newline at end of file +5d95b42946b5cf0346164aebe0a8c4f37527bc31 \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index dbe9dd3aee..acb6d67d7a 100644 --- a/src/test1.c +++ b/src/test1.c @@ -5517,6 +5517,11 @@ static int test_print_eqp( } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; rc = printExplainQueryPlan(pStmt); + /* This is needed on Windows so that a test case using this + ** function can open a read pipe and get the output of + ** printExplainQueryPlan() immediately. + */ + fflush(stdout); Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); return TCL_OK; } diff --git a/src/test_vfs.c b/src/test_vfs.c index bc8c4d3260..a8b53526d4 100644 --- a/src/test_vfs.c +++ b/src/test_vfs.c @@ -1070,7 +1070,6 @@ static int testvfs_obj_cmd( if( objc==3 ){ int nByte; if( p->pScript ){ - int i; Tcl_DecrRefCount(p->pScript); p->pScript = 0; } @@ -1223,7 +1222,6 @@ static int testvfs_obj_cmd( static void testvfs_obj_del(ClientData cd){ Testvfs *p = (Testvfs *)cd; - int i; if( p->pScript ) Tcl_DecrRefCount(p->pScript); sqlite3_vfs_unregister(p->pVfs); ckfree((char *)p->pVfs); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index cdc82f1930..f7b3b41623 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -459,6 +459,14 @@ end_of_step: return (rc&db->errMask); } +/* +** The maximum number of times that a statement will try to reparse +** itself before giving up and returning SQLITE_SCHEMA. +*/ +#ifndef SQLITE_MAX_SCHEMA_RETRY +# define SQLITE_MAX_SCHEMA_RETRY 5 +#endif + /* ** This is the top-level implementation of sqlite3_step(). Call ** sqlite3Step() to do most of the work. If a schema error occurs, @@ -477,7 +485,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ db = v->db; sqlite3_mutex_enter(db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA - && cnt++ < 5 + && cnt++ < SQLITE_MAX_SCHEMA_RETRY && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){ sqlite3_reset(pStmt); v->expired = 0; diff --git a/test/fts4aa.test b/test/fts4aa.test index f20d07660b..1131df3bec 100644 --- a/test/fts4aa.test +++ b/test/fts4aa.test @@ -22,9 +22,11 @@ ifcapable !fts3 { return } -do_test fts4aa-1.0 { +# This procedure fills an existing FTS3/FTS4 table with many entries. +# The table needs to have a single column (other than docid) named "words". +# +proc fts4aa_fill_table {} { db eval { -CREATE VIRTUAL TABLE t1 USING fts4(words, tokenize porter); BEGIN TRANSACTION; INSERT INTO t1(docid,words) VALUES(1001001,'In the beginning God created the heaven and the earth.'); INSERT INTO t1(docid,words) VALUES(1001002,'And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters.'); @@ -1561,9 +1563,41 @@ INSERT INTO t1(docid,words) VALUES(1050025,'And Joseph took an oath of the child INSERT INTO t1(docid,words) VALUES(1050026,'So Joseph died, being an hundred and ten years old: and they embalmed him, and he was put in a coffin in Egypt.'); COMMIT; } +} + +# The following is a list of queries to perform against the above +# FTS3/FTS4 database. We will be trying these queries in various +# configurations to ensure that they always return the same answers. +# +set fts4aa_queries { + {abraham} + {the king} + {"the king"} + {abraham OR joseph} + {ab* OR jos*} + {lived t*} + {spake hebrew} + {melchizedek} + {t* melchizedek} + {melchizedek t*} +} +unset -nocomplain fts4aa_res + +# Set up the baseline results +# +do_test fts4aa-1.0 { + db eval { + CREATE VIRTUAL TABLE t1 USING fts4(words, tokenize porter); + } + fts4aa_fill_table + foreach q $::fts4aa_queries { + set r [db eval {SELECT docid FROM t1 WHERE words MATCH $q ORDER BY docid}] + set ::fts4aa_res($q) $r + } } {} - +# Legacy test cases +# do_test fts4aa-1.1 { db eval { SELECT docid FROM t1 EXCEPT SELECT docid FROM t1_docsize @@ -1583,19 +1617,19 @@ proc mit {blob} { } db func mit mit -do_test fts4aa-2.1 { +do_test fts4aa-1.3 { db eval { SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1 WHERE t1 MATCH 'melchizedek'; } } {1014018 {1 1 1 1 1 1533 25 20}} -do_test fts4aa-2.2 { +do_test fts4aa-1.4 { db eval { SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1 WHERE t1 MATCH 'spake hebrew' ORDER BY docid; } } {1039014 {2 1 1 40 40 1 6 6 1533 25 42} 1039017 {2 1 1 40 40 1 6 6 1533 25 26}} -do_test fts4aa-2.3 { +do_test fts4aa-1.5 { db eval { SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1 WHERE t1 MATCH 'laban overtook jacob' @@ -1603,7 +1637,7 @@ do_test fts4aa-2.3 { } } {1031025 {3 1 2 54 46 1 3 3 2 181 160 1533 25 24}} -do_test fts4aa-9.1 { +do_test fts4aa-1.6 { db eval { DELETE FROM t1 WHERE docid!=1050026; SELECT hex(size) FROM t1_docsize; @@ -1611,17 +1645,17 @@ do_test fts4aa-9.1 { } } {17 01176F} -do_test fts4aa-9.2 { +do_test fts4aa-1.7 { db eval { SELECT docid FROM t1 EXCEPT SELECT docid FROM t1_docsize } } {} -do_test fts4aa-9.3 { +do_test fts4aa-1.8 { db eval { SELECT docid FROM t1_docsize EXCEPT SELECT docid FROM t1 } } {} -do_test fts4aa-9.4 { +do_test fts4aa-1.9 { # Note: Token 'in' is being deferred in the following query. db eval { SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1 @@ -1630,4 +1664,67 @@ do_test fts4aa-9.4 { } } {1050026 {4 1 1 1 1 1 1 1 2 1 1 1 1 1 1 23 23}} +# Should get the same search results from FTS3 +# +do_test fts4aa-2.0 { + db eval { + DROP TABLE t1; + CREATE VIRTUAL TABLE t1 USING fts3(words, tokenize porter); + } + fts4aa_fill_table +} {} +unset -nocomplain ii +set ii 0 +foreach {q r} [array get fts4aa_res] { + incr ii + do_test fts4aa-2.$ii { + db eval {SELECT docid FROM t1 WHERE words MATCH $::q ORDER BY docid} + } $r +} + +# Should get the same search results when the page size is very large +# +do_test fts4aa-3.0 { + db close + file delete -force test.db + sqlite3 db test.db + db eval { + PRAGMA page_size=65536; + CREATE VIRTUAL TABLE t1 USING fts4(words, tokenize porter); + } + fts4aa_fill_table +} {} +unset -nocomplain ii +set ii 0 +foreach {q r} [array get fts4aa_res] { + incr ii + do_test fts4aa-3.$ii { + db eval {SELECT docid FROM t1 WHERE words MATCH $::q ORDER BY docid} + } $r +} + +# Should get the same search results when an authorizer prevents +# all PRAGMA statements. +# +proc no_pragma_auth {code arg1 arg2 arg3 arg4} { + if {$code=="SQLITE_PRAGMA"} {return SQLITE_DENY} + return SQLITE_OK; +} +do_test fts4aa-4.0 { + db auth ::no_pragma_auth + db eval { + DROP TABLE t1; + CREATE VIRTUAL TABLE t1 USING fts4(words, tokenize porter); + } + fts4aa_fill_table +} {} +unset -nocomplain ii +set ii 0 +foreach {q r} [array get fts4aa_res] { + incr ii + do_test fts4aa-4.$ii { + db eval {SELECT docid FROM t1 WHERE words MATCH $::q ORDER BY docid} + } $r +} + finish_test diff --git a/test/oserror.test b/test/oserror.test index 2d3a24a8f5..bdeb868425 100644 --- a/test/oserror.test +++ b/test/oserror.test @@ -51,6 +51,7 @@ proc do_re_test {tn script expression} { # a call to getcwd() may fail if there are no free file descriptors. So # an error may be reported for either open() or getcwd() here. # +puts "Possible valgrind error about invalid file descriptor follows:" do_test 1.1.1 { set ::log [list] list [catch { diff --git a/test/triggerC.test b/test/triggerC.test index a54aa62fae..e5a492a412 100644 --- a/test/triggerC.test +++ b/test/triggerC.test @@ -228,22 +228,22 @@ foreach {n tdefn rc} { } do_test triggerC-2.2 { - execsql { + execsql " CREATE TABLE t22(x); CREATE TRIGGER t22a AFTER INSERT ON t22 BEGIN INSERT INTO t22 SELECT x + (SELECT max(x) FROM t22) FROM t22; END; CREATE TRIGGER t22b BEFORE INSERT ON t22 BEGIN - SELECT CASE WHEN (SELECT count(*) FROM t22) >= 100 + SELECT CASE WHEN (SELECT count(*) FROM t22) >= [expr $SQLITE_MAX_TRIGGER_DEPTH / 2] THEN RAISE(IGNORE) ELSE NULL END; END; INSERT INTO t22 VALUES(1); SELECT count(*) FROM t22; - } -} {100} + " +} [list [expr $SQLITE_MAX_TRIGGER_DEPTH / 2]] do_test triggerC-2.3 { execsql " diff --git a/test/wal5.test b/test/wal5.test index ad6bcfc7d8..0c700dfc50 100644 --- a/test/wal5.test +++ b/test/wal5.test @@ -235,7 +235,14 @@ foreach {testprefix do_wal_checkpoint} { do_test 2.3.$tn.5 { sql1 { INSERT INTO t2 VALUES(3, 4) } } {} do_test 2.3.$tn.6 { file_page_counts } {1 7 1 7} do_test 2.3.$tn.7 { code1 { do_wal_checkpoint db -mode full } } {1 7 5} - do_test 2.3.$tn.8 { file_page_counts } {1 7 2 7} + if {$tcl_platform(platform) == "windows"} { + # on unix, the size_hint is a no-op if no chunk size is set. + # the windows implementation does not have a similar check, + # and because of this, the db file size has an extra page. + do_test 2.3.$tn.8 { file_page_counts } {2 7 2 7} + } { + do_test 2.3.$tn.8 { file_page_counts } {1 7 2 7} + } } # Check that checkpoints block on the correct locks. And respond correctly diff --git a/tool/omittest.tcl b/tool/omittest.tcl index f1963ff13d..33a71cee26 100644 --- a/tool/omittest.tcl +++ b/tool/omittest.tcl @@ -31,8 +31,8 @@ should work. The following properties are required: More precisely, the following two invocations must be supported: - make -f $::MAKEFILE testfixture OPTS="-DSQLITE_OMIT_ALTERTABLE=1" - make -f $::MAKEFILE test + $::MAKEBIN -f $::MAKEFILE testfixture OPTS="-DSQLITE_OMIT_ALTERTABLE=1" + $::MAKEBIN -f $::MAKEFILE test Makefiles generated by the sqlite configure program cannot be used as they do not respect the OPTS variable. @@ -73,7 +73,7 @@ catch { file copy -force ./libtool $dir } set rc [catch { - exec make -C $dir -f $::MAKEFILE $target OPTS=$opts >& $dir/build.log + exec $::MAKEBIN -C $dir -f $::MAKEFILE clean $target OPTS=$opts >& $dir/build.log }] if {$rc} { puts "No good. See $dir/build.log." @@ -102,7 +102,7 @@ catch { puts -nonewline "Testing $dir..." flush stdout set rc [catch { - exec make -C $dir -f $::MAKEFILE test OPTS=$opts >& $dir/test.log + exec $::MAKEBIN -C $dir -f $::MAKEFILE test OPTS=$opts >& $dir/test.log }] if {$rc} { puts "No good. See $dir/test.log." @@ -119,8 +119,9 @@ catch { # option. # proc process_options {argv} { + set ::MAKEBIN make ;# Default value if {$::tcl_platform(platform)=="windows" || $::tcl_platform(platform)=="os2"} { - set ::MAKEFILE ./Makefile ;# Default value + set ::MAKEFILE ./Makefile ;# Default value on Windows and OS2 } else { set ::MAKEFILE ./Makefile.linux-gcc ;# Default value } @@ -133,6 +134,11 @@ proc process_options {argv} { set ::MAKEFILE [lindex $argv $i] } + -nmake { + set ::MAKEBIN nmake + set ::MAKEFILE ./Makefile.msc + } + -skip_run { set ::SKIP_RUN 1 } @@ -251,7 +257,7 @@ proc main {argv} { exit -1 } - set dirname "test_[string range $sym 7 end]" + set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]" run_quick_test $dirname $sym } else { # First try a test with all OMIT symbols except SQLITE_OMIT_FLOATING_POINT @@ -270,14 +276,14 @@ proc main {argv} { # are the OMIT_FLOATING_POINT and OMIT_PRAGMA symbols, even though we # know they will fail. It's good to be reminded of this from time to time. foreach sym $::OMIT_SYMBOLS { - set dirname "test_[string range $sym 7 end]" + set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]" run_quick_test $dirname $sym } # Try the ENABLE/DISABLE symbols one at a time. # We don't do them all at once since some are conflicting. foreach sym $::ENABLE_SYMBOLS { - set dirname "test_[string range $sym 7 end]" + set dirname "test_[regsub -nocase {^x*SQLITE_} $sym {}]" run_quick_test $dirname $sym } }